From 34fe6ad59161e0dcd57dfdc1feb6cfd1fcaa4794 Mon Sep 17 00:00:00 2001 From: Nyx Linden Date: Tue, 12 Mar 2013 22:34:15 +0000 Subject: SH-3944 WIP CHUI merge fixing re-introduced don's refactor of low-level openGL calls pulling out of llui and putting them into llrender. Took the new code from their updated versions from the CHUI merge, but put them in a place accessible to appearance utility. --- indra/newview/llappviewer.cpp | 2 +- indra/newview/llglsandbox.cpp | 8 ++++---- indra/newview/llmediactrl.cpp | 18 +++++++++--------- indra/newview/llviewerdisplay.cpp | 10 +++++----- indra/newview/llviewerwindow.cpp | 12 ++++++------ indra/newview/llworldmapview.cpp | 4 ++-- 6 files changed, 27 insertions(+), 27 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 0f77c68ec8..dac268ec92 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -803,7 +803,7 @@ bool LLAppViewer::init() LLUIImageList::getInstance(), ui_audio_callback, deferred_ui_audio_callback, - &LLUI::sGLScaleFactor); + &LLUI::getScaleFactor()); LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ; // NOW LLUI::getLanguage() should work. gDirUtilp must know the language diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 1208c9378e..60fa53f491 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -79,10 +79,10 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask) S32 top = llmax(y, mDragStartY); S32 bottom =llmin(y, mDragStartY); - left = llround((F32) left * LLUI::sGLScaleFactor.mV[VX]); - right = llround((F32) right * LLUI::sGLScaleFactor.mV[VX]); - top = llround((F32) top * LLUI::sGLScaleFactor.mV[VY]); - bottom = llround((F32) bottom * LLUI::sGLScaleFactor.mV[VY]); + left = llround((F32) left * LLUI::getScaleFactor().mV[VX]); + right = llround((F32) right * LLUI::getScaleFactor().mV[VX]); + top = llround((F32) top * LLUI::getScaleFactor().mV[VY]); + bottom = llround((F32) bottom * LLUI::getScaleFactor().mV[VY]); F32 old_far_plane = LLViewerCamera::getInstance()->getFar(); F32 old_near_plane = LLViewerCamera::getInstance()->getNear(); diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 99b4707158..2075aeed63 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -119,8 +119,8 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : if(!getDecoupleTextureSize()) { - S32 screen_width = llround((F32)getRect().getWidth() * LLUI::sGLScaleFactor.mV[VX]); - S32 screen_height = llround((F32)getRect().getHeight() * LLUI::sGLScaleFactor.mV[VY]); + S32 screen_width = llround((F32)getRect().getWidth() * LLUI::getScaleFactor().mV[VX]); + S32 screen_height = llround((F32)getRect().getHeight() * LLUI::getScaleFactor().mV[VY]); setTextureSize(screen_width, screen_height); } @@ -469,8 +469,8 @@ void LLMediaCtrl::reshape( S32 width, S32 height, BOOL called_from_parent ) { if(!getDecoupleTextureSize()) { - S32 screen_width = llround((F32)width * LLUI::sGLScaleFactor.mV[VX]); - S32 screen_height = llround((F32)height * LLUI::sGLScaleFactor.mV[VY]); + S32 screen_width = llround((F32)width * LLUI::getScaleFactor().mV[VX]); + S32 screen_height = llround((F32)height * LLUI::getScaleFactor().mV[VY]); // when floater is minimized, these sizes are negative if ( screen_height > 0 && screen_width > 0 ) @@ -667,7 +667,7 @@ bool LLMediaCtrl::ensureMediaSourceExists() mMediaSource->addObserver( this ); mMediaSource->setBackgroundColor( getBackgroundColor() ); mMediaSource->setTrustedBrowser(mTrusted); - mMediaSource->setPageZoomFactor( LLUI::sGLScaleFactor.mV[ VX ] ); + mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] ); if(mClearCache) { @@ -750,7 +750,7 @@ void LLMediaCtrl::draw() { gGL.pushUIMatrix(); { - mMediaSource->setPageZoomFactor( LLUI::sGLScaleFactor.mV[ VX ] ); + mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] ); // scale texture to fit the space using texture coords gGL.getTexUnit(0)->bind(media_texture); @@ -864,14 +864,14 @@ void LLMediaCtrl::convertInputCoords(S32& x, S32& y) coords_opengl = mMediaSource->getMediaPlugin()->getTextureCoordsOpenGL(); } - x = llround((F32)x * LLUI::sGLScaleFactor.mV[VX]); + x = llround((F32)x * LLUI::getScaleFactor().mV[VX]); if ( ! coords_opengl ) { - y = llround((F32)(y) * LLUI::sGLScaleFactor.mV[VY]); + y = llround((F32)(y) * LLUI::getScaleFactor().mV[VY]); } else { - y = llround((F32)(getRect().getHeight() - y) * LLUI::sGLScaleFactor.mV[VY]); + y = llround((F32)(getRect().getHeight() - y) * LLUI::getScaleFactor().mV[VY]); }; } diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index ffeea2f4df..02f82aba63 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1425,7 +1425,7 @@ void render_ui_2d() gGL.pushMatrix(); S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2); S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2); - gGL.scalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f); + gGL.scalef(LLUI::getScaleFactor().mV[0], LLUI::getScaleFactor().mV[1], 1.f); gGL.translatef((F32)half_width, (F32)half_height, 0.f); F32 zoom = gAgentCamera.mHUDCurZoom; gGL.scalef(zoom,zoom,1.f); @@ -1463,10 +1463,10 @@ void render_ui_2d() LLUI::sDirtyRect = last_rect; last_rect = t_rect; - last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::sGLScaleFactor.mV[0]); - last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::sGLScaleFactor.mV[0]); - last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::sGLScaleFactor.mV[1]); - last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::sGLScaleFactor.mV[1]); + last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::getScaleFactor().mV[0]); + last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::getScaleFactor().mV[0]); + last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::getScaleFactor().mV[1]); + last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::getScaleFactor().mV[1]); LLRect clip_rect(last_rect); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 383eb3c9e4..db3476850b 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2157,7 +2157,7 @@ void LLViewerWindow::reshape(S32 width, S32 height) calcDisplayScale(); - BOOL display_scale_changed = mDisplayScale != LLUI::sGLScaleFactor; + BOOL display_scale_changed = mDisplayScale != LLUI::getScaleFactor(); LLUI::setScaleFactor(mDisplayScale); // update our window rectangle @@ -2363,7 +2363,7 @@ void LLViewerWindow::draw() // scale view by UI global scale factor and aspect ratio correction factor gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f); - LLVector2 old_scale_factor = LLUI::sGLScaleFactor; + LLVector2 old_scale_factor = LLUI::getScaleFactor(); // apply camera zoom transform (for high res screenshots) F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion(); @@ -2377,7 +2377,7 @@ void LLViewerWindow::draw() (F32)getWindowHeightScaled() * -(F32)pos_y, 0.f); gGL.scalef(zoom_factor, zoom_factor, 1.f); - LLUI::sGLScaleFactor *= zoom_factor; + LLUI::getScaleFactor() *= zoom_factor; } // Draw tool specific overlay on world @@ -2425,7 +2425,7 @@ void LLViewerWindow::draw() LLFontGL::HCENTER, LLFontGL::TOP); } - LLUI::sGLScaleFactor = old_scale_factor; + LLUI::setScaleFactor(old_scale_factor); } LLUI::popMatrix(); gGL.popMatrix(); @@ -3230,8 +3230,8 @@ void LLViewerWindow::updateLayout() void LLViewerWindow::updateMouseDelta() { - S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]); - S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]); + S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::getScaleFactor().mV[VX]); + S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::getScaleFactor().mV[VY]); //RN: fix for asynchronous notification of mouse leaving window not working LLCoordWindow mouse_pos; diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index ccc513b80d..ffb0964499 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -421,7 +421,7 @@ void LLWorldMapView::draw() { // Inform the fetch mechanism of the size we need S32 draw_size = llround(sMapScale); - overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY])); + overlayimage->setKnownDrawSize(llround(draw_size * LLUI::getScaleFactor().mV[VX]), llround(draw_size * LLUI::getScaleFactor().mV[VY])); // Draw something whenever we have enough info if (overlayimage->hasGLTexture()) { @@ -1320,7 +1320,7 @@ void LLWorldMapView::drawTrackingCircle( const LLRect& rect, S32 x, S32 y, const gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.pushMatrix(); - gGL.translatef((F32)x * LLUI::sGLScaleFactor.mV[VX], (F32)y * LLUI::sGLScaleFactor.mV[VY], 0.f); + gGL.translatef((F32)x * LLUI::getScaleFactor().mV[VX], (F32)y * LLUI::getScaleFactor().mV[VY], 0.f); gl_washer_segment_2d(inner_radius, outer_radius, start_theta, end_theta, 40, color, color); gGL.popMatrix(); -- cgit v1.2.3 From 0ebcdce82bffae18459ed541f05906f625ef47e2 Mon Sep 17 00:00:00 2001 From: prep Date: Tue, 12 Mar 2013 18:53:27 -0400 Subject: WIP: merge fixes --- indra/newview/lloutputmonitorctrl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index a346909027..0682af1278 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -31,7 +31,7 @@ #include "../llui/llview.h" #include "llmutelist.h" #include "llspeakingindicatormanager.h" -#include "../llui/lluiimage.h" +//#include "../llui/lluiimage.h" class LLTextBox; class LLUICtrlFactory; -- cgit v1.2.3 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/CMakeLists.txt | 13 +- indra/newview/llaccountingcostmanager.cpp | 14 +- indra/newview/llaccountingcostmanager.h | 2 +- indra/newview/llagent.cpp | 46 +++--- indra/newview/llappearancemgr.cpp | 83 +++++++--- indra/newview/llassetuploadqueue.cpp | 83 +++++----- indra/newview/llassetuploadresponders.cpp | 81 +++++----- indra/newview/llassetuploadresponders.h | 28 ++-- indra/newview/llclassifiedstatsresponder.cpp | 13 +- indra/newview/llclassifiedstatsresponder.h | 8 +- indra/newview/llestateinfomodel.cpp | 10 +- indra/newview/lleventpoll.cpp | 45 +++--- indra/newview/llfeaturemanager.cpp | 20 ++- indra/newview/llfilepicker.cpp | 13 +- indra/newview/llfloaterabout.cpp | 40 ++--- indra/newview/llfloateravatarpicker.cpp | 11 +- indra/newview/llfloaterbuycurrencyhtml.cpp | 3 +- indra/newview/llfloaterhelpbrowser.cpp | 6 +- indra/newview/llfloatermodelpreview.cpp | 4 +- indra/newview/llfloatermodelpreview.h | 4 +- indra/newview/llfloatermodeluploadbase.cpp | 2 +- indra/newview/llfloatermodeluploadbase.h | 4 +- indra/newview/llfloaterobjectweights.cpp | 2 +- indra/newview/llfloaterobjectweights.h | 2 +- indra/newview/llfloaterregiondebugconsole.cpp | 16 +- indra/newview/llfloaterregioninfo.cpp | 25 +-- indra/newview/llfloaterreporter.cpp | 14 +- indra/newview/llfloaterscriptlimits.cpp | 63 +++++--- indra/newview/llfloaterscriptlimits.h | 62 ++++---- indra/newview/llfloatersearch.cpp | 3 +- indra/newview/llfloatertos.cpp | 68 ++++---- indra/newview/llfloaterurlentry.cpp | 48 +++--- indra/newview/llfloaterurlentry.h | 2 +- indra/newview/llfloaterwebcontent.cpp | 7 +- indra/newview/llgroupmgr.cpp | 26 +-- indra/newview/llhomelocationresponder.cpp | 35 ++-- indra/newview/llhomelocationresponder.h | 6 +- indra/newview/llimfloater.cpp | 7 +- indra/newview/llimpanel.cpp | 7 +- indra/newview/llimview.cpp | 30 ++-- indra/newview/llinspectavatar.cpp | 8 +- indra/newview/llinventorymodel.cpp | 30 ++-- indra/newview/llinventorymodel.h | 5 +- indra/newview/llinventorymodelbackgroundfetch.cpp | 43 +++-- indra/newview/llmarketplacefunctions.cpp | 63 ++++---- indra/newview/llmediactrl.cpp | 5 +- indra/newview/llmediadataclient.cpp | 52 +++--- indra/newview/llmediadataclient.h | 29 ++-- indra/newview/llmeshrepository.cpp | 140 ++++++++-------- indra/newview/llpanelclassified.cpp | 10 +- indra/newview/llpanellandmarks.cpp | 2 +- indra/newview/llpanellandmarks.h | 2 +- indra/newview/llpanellogin.cpp | 4 +- indra/newview/llpanelpick.h | 2 +- indra/newview/llpanelplaceinfo.cpp | 6 +- indra/newview/llpanelplaceinfo.h | 2 +- indra/newview/llpanelplaces.cpp | 2 +- indra/newview/llpathfindingmanager.cpp | 176 +++++++++------------ indra/newview/llpathfindingnavmesh.cpp | 4 +- indra/newview/llpathfindingnavmesh.h | 2 +- indra/newview/llproductinforequest.cpp | 18 ++- indra/newview/llremoteparcelrequest.cpp | 17 +- indra/newview/llremoteparcelrequest.h | 9 +- indra/newview/llspeakers.cpp | 8 +- indra/newview/lltexturefetch.cpp | 10 +- indra/newview/lltranslate.cpp | 18 +-- indra/newview/lltranslate.h | 7 - indra/newview/lluploadfloaterobservers.cpp | 20 ++- indra/newview/lluploadfloaterobservers.h | 19 ++- indra/newview/llviewerdisplayname.cpp | 14 +- indra/newview/llviewermedia.cpp | 122 +++++++------- indra/newview/llviewerobjectlist.cpp | 24 +-- indra/newview/llviewerparcelmedia.cpp | 2 +- indra/newview/llviewerregion.cpp | 104 +++++++----- indra/newview/llviewerstats.cpp | 19 +-- indra/newview/llviewerwindow.cpp | 4 +- indra/newview/llvoavatarself.cpp | 45 +++--- indra/newview/llvoicechannel.cpp | 21 ++- indra/newview/llvoicevivox.cpp | 46 +++--- indra/newview/llwebprofile.cpp | 53 ++++--- indra/newview/llwebsharing.cpp | 176 +++++++++------------ indra/newview/llwlhandlers.cpp | 27 ++-- indra/newview/llwlhandlers.h | 14 +- indra/newview/llxmlrpctransaction.cpp | 2 +- indra/newview/tests/llmediadataclient_test.cpp | 8 +- indra/newview/tests/llremoteparcelrequest_test.cpp | 16 +- indra/newview/tests/lltranslate_test.cpp | 12 +- 87 files changed, 1292 insertions(+), 1086 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index baedac1f2d..eb41c0aa3a 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -2068,10 +2068,21 @@ if (LL_TESTS) #llviewertexturelist.cpp ) + set(test_libs + ${JSONCPP_LIBRARIES} + ${CURL_LIBRARIES} + ) + set_source_files_properties( lltranslate.cpp PROPERTIES - LL_TEST_ADDITIONAL_LIBRARIES "${JSONCPP_LIBRARIES}" + LL_TEST_ADDITIONAL_LIBRARIES "${test_libs}" + ) + + set_source_files_properties( + llmediadataclient.cpp + PROPERTIES + LL_TEST_ADDITIONAL_LIBRARIES "${CURL_LIBRARIES}" ) set_source_files_properties( diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp index 7662a9689d..55d453cdcc 100644 --- a/indra/newview/llaccountingcostmanager.cpp +++ b/indra/newview/llaccountingcostmanager.cpp @@ -36,6 +36,7 @@ LLAccountingCostManager::LLAccountingCostManager() //=============================================================================== class LLAccountingCostResponder : public LLCurl::Responder { + LOG_CLASS(LLAccountingCostResponder); public: LLAccountingCostResponder( const LLSD& objectIDs, const LLHandle& observer_handle ) : mObjectIDs( objectIDs ), @@ -56,24 +57,27 @@ public: } } - void errorWithContent( U32 statusNum, const std::string& reason, const LLSD& content ) +protected: + void httpFailure() { - llwarns << "Transport error [status:" << statusNum << "]: " << content <getTransactionID() == mTransactionID) { - observer->setErrorStatus(statusNum, reason); + observer->setErrorStatus(getStatus(), getReason()); } } - void result( const LLSD& content ) + void httpSuccess() { + const LLSD& content = getContent(); //Check for error if ( !content.isMap() || content.has("error") ) { - llwarns << "Error on fetched data"<< llendl; + failureResult(HTTP_INTERNAL_ERROR, "Error on fetched data", content); + return; } else if (content.has("selected")) { diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h index 0bca1f54ef..3ade34c81d 100644 --- a/indra/newview/llaccountingcostmanager.h +++ b/indra/newview/llaccountingcostmanager.h @@ -38,7 +38,7 @@ public: LLAccountingCostObserver() { mObserverHandle.bind(this); } virtual ~LLAccountingCostObserver() {} virtual void onWeightsUpdate(const SelectionCost& selection_cost) = 0; - virtual void setErrorStatus(U32 status, const std::string& reason) = 0; + virtual void setErrorStatus(S32 status, const std::string& reason) = 0; const LLHandle& getObserverHandle() const { return mObserverHandle; } const LLUUID& getTransactionID() { return mTransactionID; } diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 20954e4bae..4b0f451036 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -2546,17 +2546,19 @@ int LLAgent::convertTextToMaturity(char text) class LLMaturityPreferencesResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLMaturityPreferencesResponder); public: LLMaturityPreferencesResponder(LLAgent *pAgent, U8 pPreferredMaturity, U8 pPreviousMaturity); virtual ~LLMaturityPreferencesResponder(); - virtual void result(const LLSD &pContent); - virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); +protected: + virtual void httpSuccess(); + virtual void httpFailure(); protected: private: - U8 parseMaturityFromServerResponse(const LLSD &pContent); + U8 parseMaturityFromServerResponse(const LLSD &pContent) const; LLAgent *mAgent; U8 mPreferredMaturity; @@ -2575,29 +2577,33 @@ LLMaturityPreferencesResponder::~LLMaturityPreferencesResponder() { } -void LLMaturityPreferencesResponder::result(const LLSD &pContent) +void LLMaturityPreferencesResponder::httpSuccess() { - U8 actualMaturity = parseMaturityFromServerResponse(pContent); + U8 actualMaturity = parseMaturityFromServerResponse(getContent()); if (actualMaturity != mPreferredMaturity) { - llwarns << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity) - << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', the server responded with '" - << LLViewerRegion::accessToString(actualMaturity) << "' [value:" << static_cast(actualMaturity) << ", llsd:" - << pContent << "]" << llendl; + llwarns << "while attempting to change maturity preference from '" + << LLViewerRegion::accessToString(mPreviousMaturity) + << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) + << "', the server responded with '" + << LLViewerRegion::accessToString(actualMaturity) + << "' [value:" << static_cast(actualMaturity) + << "], " << dumpResponse() << llendl; } mAgent->handlePreferredMaturityResult(actualMaturity); } -void LLMaturityPreferencesResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent) +void LLMaturityPreferencesResponder::httpFailure() { - llwarns << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity) - << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', we got an error with [status:" - << pStatus << "]: " << (pContent.isDefined() ? pContent : LLSD(pReason)) << llendl; + llwarns << "while attempting to change maturity preference from '" + << LLViewerRegion::accessToString(mPreviousMaturity) + << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) + << "', " << dumpResponse() << llendl; mAgent->handlePreferredMaturityError(); } -U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &pContent) +U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &pContent) const { // stinson 05/24/2012 Pathfinding regions have re-defined the response behavior. In the old server code, // if you attempted to change the preferred maturity to the same value, the response content would be an @@ -2605,7 +2611,7 @@ U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &p // defined. Thus, the check for isUndefined() can be replaced with an assert after pathfinding is merged // into server trunk and fully deployed. U8 maturity = SIM_ACCESS_MIN; - if (pContent.isUndefined()) + if (pContent.isUndefined() || !pContent.isMap()) { maturity = mPreferredMaturity; } @@ -2783,7 +2789,7 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) // If we don't have a region, report it as an error if (getRegion() == NULL) { - responderPtr->errorWithContent(0U, "region is not defined", LLSD()); + responderPtr->failureResult(0U, "region is not defined", LLSD()); } else { @@ -2793,7 +2799,7 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity) // If the capability is not defined, report it as an error if (url.empty()) { - responderPtr->errorWithContent(0U, + responderPtr->failureResult(0U, "capability 'UpdateAgentInformation' is not defined for region", LLSD()); } else @@ -3292,8 +3298,7 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode !input.has("body") ) { //what to do with badly formed message? - response->statusUnknownError(400); - response->result(LLSD("Invalid message parameters")); + response->extendedResult(HTTP_BAD_REQUEST, LLSD("Invalid message parameters")); } LLSD body = input["body"]; @@ -3362,8 +3367,7 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode else { //what to do with badly formed message? - response->statusUnknownError(400); - response->result(LLSD("Invalid message parameters")); + response->extendedResult(HTTP_BAD_REQUEST, LLSD("Invalid message parameters")); } } }; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 2c76efc7fb..92a896a3c2 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2984,20 +2984,23 @@ class LLHTTPRetryPolicy: public LLThreadSafeRefCount public: LLHTTPRetryPolicy() {} virtual ~LLHTTPRetryPolicy() {} - virtual bool shouldRetry(U32 status, F32& seconds_to_wait) = 0; + virtual bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) = 0; }; // Example of simplest possible policy, not necessarily recommended. +// This would be a potentially dangerous policy to enable. Removing for now: +#if 0 class LLAlwaysRetryImmediatelyPolicy: public LLHTTPRetryPolicy { public: LLAlwaysRetryImmediatelyPolicy() {} - bool shouldRetry(U32 status, F32& seconds_to_wait) + bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) { seconds_to_wait = 0.0; return true; } }; +#endif // Very general policy with geometric back-off after failures, // up to a maximum delay, and maximum number of retries. @@ -3014,10 +3017,25 @@ public: { } - bool shouldRetry(U32 status, F32& seconds_to_wait) + bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) { - seconds_to_wait = mDelay; - mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay); +#if 0 + // *TODO: Test using status codes to only retry server errors. + // Only server errors would potentially return a different result on retry. + if (!isHttpServerErrorStatus(status)) return false; +#endif + +#if 0 + // *TODO: Honor server Retry-After header. + // Status 503 may ask us to wait for a certain amount of time before retrying. + if (!headers.has(HTTP_HEADER_RETRY_AFTER) + || !getSecondsUntilRetryAfter(headers[HTTP_HEADER_RETRY_AFTER].asStringRef(), seconds_to_wait)) +#endif + { + seconds_to_wait = mDelay; + mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay); + } + mRetryCount++; return (mRetryCount<=mMaxRetries); } @@ -3033,6 +3051,7 @@ private: class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder { + LOG_CLASS(RequestAgentUpdateAppearanceResponder); public: RequestAgentUpdateAppearanceResponder() { @@ -3043,13 +3062,19 @@ public: { } +protected: // Successful completion. - /* virtual */ void result(const LLSD& content) + /* virtual */ void httpSuccess() { - LL_DEBUGS("Avatar") << "content: " << ll_pretty_print_sd(content) << LL_ENDL; + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } if (content["success"].asBoolean()) { - LL_DEBUGS("Avatar") << "OK" << LL_ENDL; + LL_DEBUGS("Avatar") << dumpResponse() << LL_ENDL; if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) { dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_ok", content); @@ -3057,33 +3082,35 @@ public: } else { - onFailure(200); + failureResult(HTTP_INTERNAL_ERROR, "Non-success response", content); } } // Error - /*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + /*virtual*/ void httpFailure() { - llwarns << "appearance update request failed, status: " << status << " reason: " << reason << " code: " << content["code"].asInteger() << " error: \"" << content["error"].asString() << "\"" << llendl; + const LLSD& content = getContent(); + LL_WARNS("Avatar") << "appearance update request failed " + << dumpResponse() << LL_ENDL; if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) { dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_error", content); debugCOF(content); } - onFailure(status); - } + onFailure(); + } - void onFailure(U32 status) + void onFailure() { F32 seconds_to_wait; - if (mRetryPolicy->shouldRetry(status,seconds_to_wait)) + if (mRetryPolicy->shouldRetry(getStatus(), getResponseHeaders(), seconds_to_wait)) { llinfos << "retrying" << llendl; doAfterInterval(boost::bind(&LLAppearanceMgr::requestServerAppearanceUpdate, LLAppearanceMgr::getInstance(), - LLCurl::ResponderPtr(this)), - seconds_to_wait); + LLHTTPClient::ResponderPtr(this)), + seconds_to_wait); } else { @@ -3286,6 +3313,7 @@ void LLAppearanceMgr::requestServerAppearanceUpdate(LLCurl::ResponderPtr respond class LLIncrementCofVersionResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLIncrementCofVersionResponder); public: LLIncrementCofVersionResponder() : LLHTTPClient::Responder() { @@ -3296,10 +3324,17 @@ public: { } - virtual void result(const LLSD &pContent) +protected: + virtual void httpSuccess() { llinfos << "Successfully incremented agent's COF." << llendl; - S32 new_version = pContent["category"]["version"].asInteger(); + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + S32 new_version = content["category"]["version"].asInteger(); LLAppearanceMgr* app_mgr = LLAppearanceMgr::getInstance(); @@ -3308,12 +3343,13 @@ public: app_mgr->mLastUpdateRequestCOFVersion = new_version; } - virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& content) + + virtual void httpFailure() { - llwarns << "While attempting to increment the agent's cof we got an error with [status:" - << pStatus << "]: " << content << llendl; + LL_WARNS("Avatar") << "While attempting to increment the agent's cof we got an error " + << dumpResponse() << LL_ENDL; F32 seconds_to_wait; - if (mRetryPolicy->shouldRetry(pStatus,seconds_to_wait)) + if (mRetryPolicy->shouldRetry(getStatus(), getResponseHeaders(), seconds_to_wait)) { llinfos << "retrying" << llendl; doAfterInterval(boost::bind(&LLAppearanceMgr::incrementCofVersion, @@ -3327,6 +3363,7 @@ public: } } +private: LLPointer mRetryPolicy; }; diff --git a/indra/newview/llassetuploadqueue.cpp b/indra/newview/llassetuploadqueue.cpp index 4bdb690225..cde9bc9dc0 100644 --- a/indra/newview/llassetuploadqueue.cpp +++ b/indra/newview/llassetuploadqueue.cpp @@ -36,6 +36,7 @@ class LLAssetUploadChainResponder : public LLUpdateTaskInventoryResponder { + LOG_CLASS(LLAssetUploadChainResponder); public: LLAssetUploadChainResponder(const LLSD& post_data, @@ -51,52 +52,54 @@ public: mDataSize(data_size), mScriptName(script_name) { - } + } virtual ~LLAssetUploadChainResponder() - { - if(mSupplier) - { - LLAssetUploadQueue *queue = mSupplier->get(); - if (queue) - { - // Give ownership of supplier back to queue. - queue->mSupplier = mSupplier; - mSupplier = NULL; - } - } - delete mSupplier; + { + if(mSupplier) + { + LLAssetUploadQueue *queue = mSupplier->get(); + if (queue) + { + // Give ownership of supplier back to queue. + queue->mSupplier = mSupplier; + mSupplier = NULL; + } + } + delete mSupplier; delete mData; - } + } - virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) - { - llwarns << "LLAssetUploadChainResponder Error [status:" - << statusNum << "]: " << content << llendl; - LLUpdateTaskInventoryResponder::errorWithContent(statusNum, reason, content); - LLAssetUploadQueue *queue = mSupplier->get(); - if (queue) +protected: + virtual void httpFailure() + { + // Parent class will spam the failure. + //llwarns << dumpResponse() << llendl; + LLUpdateTaskInventoryResponder::httpFailure(); + LLAssetUploadQueue *queue = mSupplier->get(); + if (queue) + { + queue->request(&mSupplier); + } + } + + virtual void httpSuccess() + { + LLUpdateTaskInventoryResponder::httpSuccess(); + LLAssetUploadQueue *queue = mSupplier->get(); + if (queue) { - queue->request(&mSupplier); - } - } - - virtual void result(const LLSD& content) - { - LLUpdateTaskInventoryResponder::result(content); - LLAssetUploadQueue *queue = mSupplier->get(); - if (queue) - { - // Responder is reused across 2 phase upload, - // so only start next upload after 2nd phase complete. - std::string state = content["state"]; - if(state == "complete") - { - queue->request(&mSupplier); - } - } - } + // Responder is reused across 2 phase upload, + // so only start next upload after 2nd phase complete. + const std::string& state = getContent()["state"].asStringRef(); + if(state == "complete") + { + queue->request(&mSupplier); + } + } + } +public: virtual void uploadUpload(const LLSD& content) { std::string uploader = content["uploader"]; diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 2564802387..ea511b18e2 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -225,37 +225,41 @@ LLAssetUploadResponder::~LLAssetUploadResponder() } // virtual -void LLAssetUploadResponder::errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) +void LLAssetUploadResponder::httpFailure() { - llinfos << "LLAssetUploadResponder::error [status:" - << statusNum << "]: " << content << llendl; + // *TODO: Add adaptive retry policy? + llwarns << dumpResponse() << llendl; LLSD args; - switch(statusNum) + if (isHttpClientErrorStatus(getStatus())) { - case 400: - args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName); - args["REASON"] = "Error in upload request. Please visit " - "http://secondlife.com/support for help fixing this problem."; - LLNotificationsUtil::add("CannotUploadReason", args); - break; - case 500: - default: - args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName); - args["REASON"] = "The server is experiencing unexpected " - "difficulties."; - LLNotificationsUtil::add("CannotUploadReason", args); - break; + args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName); + args["REASON"] = "Error in upload request. Please visit " + "http://secondlife.com/support for help fixing this problem."; + LLNotificationsUtil::add("CannotUploadReason", args); + } + else + { + args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName); + args["REASON"] = "The server is experiencing unexpected " + "difficulties."; + LLNotificationsUtil::add("CannotUploadReason", args); } LLUploadDialog::modalUploadFinished(); LLFilePicker::instance().reset(); // unlock file picker when bulk upload fails } //virtual -void LLAssetUploadResponder::result(const LLSD& content) +void LLAssetUploadResponder::httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } lldebugs << "LLAssetUploadResponder::result from capabilities" << llendl; - std::string state = content["state"]; + const std::string& state = content["state"].asStringRef(); if (state == "upload") { @@ -280,7 +284,7 @@ void LLAssetUploadResponder::result(const LLSD& content) void LLAssetUploadResponder::uploadUpload(const LLSD& content) { - std::string uploader = content["uploader"]; + const std::string& uploader = content["uploader"].asStringRef(); if (mFileName.empty()) { LLHTTPClient::postFile(uploader, mVFileID, mAssetType, this); @@ -293,6 +297,7 @@ void LLAssetUploadResponder::uploadUpload(const LLSD& content) void LLAssetUploadResponder::uploadFailure(const LLSD& content) { + llwarns << dumpResponse() << llendl; // remove the "Uploading..." message LLUploadDialog::modalUploadFinished(); LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot"); @@ -301,7 +306,7 @@ void LLAssetUploadResponder::uploadFailure(const LLSD& content) floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory"))); } - std::string reason = content["state"]; + const std::string& reason = content["state"].asStringRef(); // deal with L$ errors if (reason == "insufficient funds") { @@ -340,9 +345,9 @@ LLNewAgentInventoryResponder::LLNewAgentInventoryResponder( } // virtual -void LLNewAgentInventoryResponder::errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) +void LLNewAgentInventoryResponder::httpFailure() { - LLAssetUploadResponder::errorWithContent(statusNum, reason, content); + LLAssetUploadResponder::httpFailure(); //LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, LLUUID(), FALSE); } @@ -487,10 +492,9 @@ void LLSendTexLayerResponder::uploadComplete(const LLSD& content) } } -void LLSendTexLayerResponder::errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) +void LLSendTexLayerResponder::httpFailure() { - llinfos << "LLSendTexLayerResponder error [status:" - << statusNum << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; // Invoke the original callback with an error result LLViewerTexLayerSetBuffer::onTextureUploadComplete(LLUUID(), (void*) mBakedUploadData, -1, LL_EXSTAT_NONE); @@ -1009,19 +1013,14 @@ LLNewAgentInventoryVariablePriceResponder::~LLNewAgentInventoryVariablePriceResp delete mImpl; } -void LLNewAgentInventoryVariablePriceResponder::errorWithContent( - U32 statusNum, - const std::string& reason, - const LLSD& content) +void LLNewAgentInventoryVariablePriceResponder::httpFailure() { - lldebugs - << "LLNewAgentInventoryVariablePrice::error " << statusNum - << " reason: " << reason << llendl; + const LLSD& content = getContent(); + LL_WARNS("Upload") << dumpResponse() << LL_ENDL; - if ( content.has("error") ) + static const std::string _ERROR = "error"; + if ( content.has(_ERROR) ) { - static const std::string _ERROR = "error"; - mImpl->onTransportError(content[_ERROR]); } else @@ -1030,8 +1029,14 @@ void LLNewAgentInventoryVariablePriceResponder::errorWithContent( } } -void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content) +void LLNewAgentInventoryVariablePriceResponder::httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } // Parse out application level errors and the appropriate // responses for them static const std::string _ERROR = "error"; @@ -1047,6 +1052,7 @@ void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content) // Check for application level errors if ( content.has(_ERROR) ) { + LL_WARNS("Upload") << dumpResponse() << LL_ENDL; onApplicationLevelError(content[_ERROR]); return; } @@ -1090,6 +1096,7 @@ void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content) } else { + LL_WARNS("Upload") << dumpResponse() << LL_ENDL; onApplicationLevelError(""); } } diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index a6d1016136..abfdc4ca77 100644 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -33,6 +33,8 @@ // via capabilities class LLAssetUploadResponder : public LLHTTPClient::Responder { +protected: + LOG_CLASS(LLAssetUploadResponder); public: LLAssetUploadResponder(const LLSD& post_data, const LLUUID& vfile_id, @@ -42,8 +44,11 @@ public: LLAssetType::EType asset_type); ~LLAssetUploadResponder(); - virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content); - virtual void result(const LLSD& content); +protected: + virtual void httpFailure(); + virtual void httpSuccess(); + +public: virtual void uploadUpload(const LLSD& content); virtual void uploadComplete(const LLSD& content); virtual void uploadFailure(const LLSD& content); @@ -58,6 +63,7 @@ protected: // TODO*: Remove this once deprecated class LLNewAgentInventoryResponder : public LLAssetUploadResponder { + LOG_CLASS(LLNewAgentInventoryResponder); public: LLNewAgentInventoryResponder( const LLSD& post_data, @@ -67,9 +73,10 @@ public: const LLSD& post_data, const std::string& file_name, LLAssetType::EType asset_type); - virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content); virtual void uploadComplete(const LLSD& content); virtual void uploadFailure(const LLSD& content); +protected: + virtual void httpFailure(); }; // A base class which goes through and performs some default @@ -79,6 +86,7 @@ public: class LLNewAgentInventoryVariablePriceResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLNewAgentInventoryVariablePriceResponder); public: LLNewAgentInventoryVariablePriceResponder( const LLUUID& vfile_id, @@ -91,12 +99,11 @@ public: const LLSD& inventory_info); virtual ~LLNewAgentInventoryVariablePriceResponder(); - void errorWithContent( - U32 statusNum, - const std::string& reason, - const LLSD& content); - void result(const LLSD& content); +private: + /* virtual */ void httpFailure(); + /* virtual */ void httpSuccess(); +public: virtual void onApplicationLevelError( const LLSD& error); virtual void showConfirmationDialog( @@ -122,8 +129,11 @@ public: ~LLSendTexLayerResponder(); virtual void uploadComplete(const LLSD& content); - virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content); +protected: + virtual void httpFailure(); + +private: LLBakedUploadData * mBakedUploadData; }; diff --git a/indra/newview/llclassifiedstatsresponder.cpp b/indra/newview/llclassifiedstatsresponder.cpp index e3cd83e174..923662e887 100644 --- a/indra/newview/llclassifiedstatsresponder.cpp +++ b/indra/newview/llclassifiedstatsresponder.cpp @@ -44,8 +44,14 @@ mClassifiedID(classified_id) } /*virtual*/ -void LLClassifiedStatsResponder::result(const LLSD& content) +void LLClassifiedStatsResponder::httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } S32 teleport = content["teleport_clicks"].asInteger(); S32 map = content["map_clicks"].asInteger(); S32 profile = content["profile_clicks"].asInteger(); @@ -62,7 +68,8 @@ void LLClassifiedStatsResponder::result(const LLSD& content) } /*virtual*/ -void LLClassifiedStatsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLClassifiedStatsResponder::httpFailure() { - llinfos << "LLClassifiedStatsResponder::error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; } + diff --git a/indra/newview/llclassifiedstatsresponder.h b/indra/newview/llclassifiedstatsresponder.h index 06dcb62fd0..efa4d82411 100644 --- a/indra/newview/llclassifiedstatsresponder.h +++ b/indra/newview/llclassifiedstatsresponder.h @@ -33,13 +33,15 @@ class LLClassifiedStatsResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLClassifiedStatsResponder); public: LLClassifiedStatsResponder(LLUUID classified_id); + +protected: //If we get back a normal response, handle it here - virtual void result(const LLSD& content); + virtual void httpSuccess(); //If we get back an error (not found, etc...), handle it here - - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); + virtual void httpFailure(); protected: LLUUID mClassifiedID; diff --git a/indra/newview/llestateinfomodel.cpp b/indra/newview/llestateinfomodel.cpp index 2669b0340f..db2c15a444 100644 --- a/indra/newview/llestateinfomodel.cpp +++ b/indra/newview/llestateinfomodel.cpp @@ -112,19 +112,19 @@ void LLEstateInfoModel::notifyCommit() class LLEstateChangeInfoResponder : public LLHTTPClient::Responder { -public: - + LOG_CLASS(LLEstateChangeInfoResponder); +protected: // if we get a normal response, handle it here - virtual void result(const LLSD& content) + virtual void httpSuccesss() { llinfos << "Committed estate info" << llendl; LLEstateInfoModel::instance().notifyCommit(); } // if we get an error response - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + virtual void httpFailure() { - llwarns << "Failed to commit estate info [status:" << status << "]: " << content << llendl; + llwarns << "Failed to commit estate info " << dumpResponse() << llendl; } }; diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index e0f7223a8c..c3b53d5e4a 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -31,7 +31,7 @@ #include "llagent.h" #include "llhttpclient.h" -#include "llhttpstatuscodes.h" +#include "llhttpconstants.h" #include "llsdserialize.h" #include "lleventtimer.h" #include "llviewerregion.h" @@ -49,6 +49,7 @@ namespace class LLEventPollResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLEventPollResponder); public: static LLHTTPClient::ResponderPtr start(const std::string& pollURL, const LLHost& sender); @@ -56,19 +57,19 @@ namespace void makeRequest(); + /* virtual */ void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + private: LLEventPollResponder(const std::string& pollURL, const LLHost& sender); ~LLEventPollResponder(); void handleMessage(const LLSD& content); - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); - virtual void result(const LLSD& content); - virtual void completedRaw(U32 status, - const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer); + /* virtual */ void httpFailure(); + /* virtual */ void httpSuccess(); + private: bool mDone; @@ -149,20 +150,18 @@ namespace } // virtual - void LLEventPollResponder::completedRaw(U32 status, - const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) + void LLEventPollResponder::completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) { - if (status == HTTP_BAD_GATEWAY) + if (getStatus() == HTTP_BAD_GATEWAY) { // These errors are not parsable as LLSD, // which LLHTTPClient::Responder::completedRaw will try to do. - completed(status, reason, LLSD()); + httpCompleted(); } else { - LLHTTPClient::Responder::completedRaw(status,reason,channels,buffer); + LLHTTPClient::Responder::completedRaw(channels,buffer); } } @@ -187,13 +186,13 @@ namespace } //virtual - void LLEventPollResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) + void LLEventPollResponder::httpFailure() { if (mDone) return; // A HTTP_BAD_GATEWAY (502) error is our standard timeout response // we get this when there are no events. - if ( status == HTTP_BAD_GATEWAY ) + if ( getStatus() == HTTP_BAD_GATEWAY ) { mErrorCount = 0; makeRequest(); @@ -207,12 +206,12 @@ namespace + mErrorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC , this); - llwarns << "LLEventPollResponder error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; } else { - llwarns << "LLEventPollResponder error <" << mCount - << "> [status:" << status << "]: " << content + llwarns << dumpResponse() + << " [count:" << mCount << "] " << (mDone ? " -- done" : "") << llendl; stop(); @@ -234,7 +233,7 @@ namespace } //virtual - void LLEventPollResponder::result(const LLSD& content) + void LLEventPollResponder::httpSuccess() { lldebugs << "LLEventPollResponder::result <" << mCount << ">" << (mDone ? " -- done" : "") << llendl; @@ -243,10 +242,12 @@ namespace mErrorCount = 0; - if (!content.get("events") || + const LLSD& content = getContent(); + if (!content.isMap() || + !content.get("events") || !content.get("id")) { - llwarns << "received event poll with no events or id key" << llendl; + llwarns << "received event poll with no events or id key: " << dumpResponse() << llendl; makeRequest(); return; } diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index a4cadcd5dc..c4ae718082 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -39,6 +39,7 @@ #include "llsecondlifeurls.h" #include "llappviewer.h" +#include "llbufferstream.h" #include "llhttpclient.h" #include "llnotificationsutil.h" #include "llviewercontrol.h" @@ -509,6 +510,7 @@ void LLFeatureManager::parseGPUTable(std::string filename) // responder saves table into file class LLHTTPFeatureTableResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLHTTPFeatureTableResponder); public: LLHTTPFeatureTableResponder(std::string filename) : @@ -517,11 +519,10 @@ public: } - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, + virtual void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { - if (isGoodStatus(status)) + if (isGoodStatus()) { // write to file @@ -540,7 +541,18 @@ public: out.close(); } } - + else + { + char body[1025]; + body[1024] = '\0'; + LLBufferStream istr(channels, buffer.get()); + istr.get(body,1024); + if (strlen(body) > 0) + { + mContent["body"] = body; + } + llwarns << dumpResponse() << llendl; + } } private: diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index d13f85baa2..89d74666f7 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -1240,9 +1240,9 @@ static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker) { GtkFileFilter *gfilter = gtk_file_filter_new(); gtk_file_filter_add_pattern(gfilter, "*.tga"); - gtk_file_filter_add_mime_type(gfilter, "image/jpeg"); - gtk_file_filter_add_mime_type(gfilter, "image/png"); - gtk_file_filter_add_mime_type(gfilter, "image/bmp"); + gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_JPEG.c_str()); + gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_PNG.c_str()); + gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_BMP.c_str()); std::string filtername = LLTrans::getString("image_files") + " (*.tga; *.bmp; *.jpg; *.png)"; add_common_filters_to_gtkchooser(gfilter, picker, filtername); return filtername; @@ -1250,13 +1250,13 @@ static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker) static std::string add_script_filter_to_gtkchooser(GtkWindow *picker) { - return add_simple_mime_filter_to_gtkchooser(picker, "text/plain", + return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN, LLTrans::getString("script_files") + " (*.lsl)"); } static std::string add_dictionary_filter_to_gtkchooser(GtkWindow *picker) { - return add_simple_mime_filter_to_gtkchooser(picker, "text/plain", + return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN, LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)"); } @@ -1294,7 +1294,7 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename break; case FFSAVE_BMP: caption += add_simple_mime_filter_to_gtkchooser - (picker, "image/bmp", LLTrans::getString("bitmap_image_files") + " (*.bmp)"); + (picker, HTTP_CONTENT_IMAGE_BMP, LLTrans::getString("bitmap_image_files") + " (*.bmp)"); suggest_ext = ".bmp"; break; case FFSAVE_AVI: @@ -1319,6 +1319,7 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename suggest_ext = ".raw"; break; case FFSAVE_J2C: + // *TODO: Should this be 'image/j2c' ? caption += add_simple_mime_filter_to_gtkchooser (picker, "images/jp2", LLTrans::getString("compressed_image_files") + " (*.j2c)"); diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 83fb887d81..63888ace11 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -77,14 +77,9 @@ class LLServerReleaseNotesURLFetcher : public LLHTTPClient::Responder { LOG_CLASS(LLServerReleaseNotesURLFetcher); public: - static void startFetch(); - /*virtual*/ void completedHeader(U32 status, const std::string& reason, const LLSD& content); - /*virtual*/ void completedRaw( - U32 status, - const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer); +private: + /* virtual */ void httpCompleted(); }; ///---------------------------------------------------------------------------- @@ -471,32 +466,27 @@ void LLServerReleaseNotesURLFetcher::startFetch() } // virtual -void LLServerReleaseNotesURLFetcher::completedHeader(U32 status, const std::string& reason, const LLSD& content) +void LLServerReleaseNotesURLFetcher::httpCompleted() { - lldebugs << "Status: " << status << llendl; - lldebugs << "Reason: " << reason << llendl; - lldebugs << "Headers: " << content << llendl; + LL_DEBUGS("ServerReleaseNotes") << dumpResponse() + << " [headers:" << getResponseHeaders() << "]" << LL_ENDL; LLFloaterAbout* floater_about = LLFloaterReg::getTypedInstance("sl_about"); if (floater_about) { - std::string location = content["location"].asString(); + const bool check_lower = true; + const std::string& location = getResponseHeader(HTTP_HEADER_LOCATION, check_lower); if (location.empty()) { - location = floater_about->getString("ErrorFetchingServerReleaseNotesURL"); + LL_WARNS("ServerReleaseNotes") << "Missing Location header " + << dumpResponse() << " [headers:" << getResponseHeaders() << "]" << LL_ENDL; + floater_about->updateServerReleaseNotesURL( + floater_about->getString("ErrorFetchingServerReleaseNotesURL")); + } + else + { + floater_about->updateServerReleaseNotesURL(location); } - floater_about->updateServerReleaseNotesURL(location); } } -// virtual -void LLServerReleaseNotesURLFetcher::completedRaw( - U32 status, - const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) -{ - // Do nothing. - // We're overriding just because the base implementation tries to - // deserialize LLSD which triggers warnings. -} diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 752aba5e16..eaf4d062fe 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -380,12 +380,14 @@ BOOL LLFloaterAvatarPicker::visibleItemsSelected() const class LLAvatarPickerResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLAvatarPickerResponder); public: LLUUID mQueryID; LLAvatarPickerResponder(const LLUUID& id) : mQueryID(id) { } - /*virtual*/ void completed(U32 status, const std::string& reason, const LLSD& content) +protected: + /*virtual*/ void httpCompleted() { //std::ostringstream ss; //LLSDSerialize::toPrettyXML(content, ss); @@ -393,19 +395,18 @@ public: // in case of invalid characters, the avatar picker returns a 400 // just set it to process so it displays 'not found' - if (isGoodStatus(status) || status == 400) + if (isGoodStatus() || getStatus() == HTTP_BAD_REQUEST) { LLFloaterAvatarPicker* floater = LLFloaterReg::findTypedInstance("avatar_picker"); if (floater) { - floater->processResponse(mQueryID, content); + floater->processResponse(mQueryID, getContent()); } } else { - llwarns << "avatar picker failed [status:" << status << "]: " << content << llendl; - + llwarns << "avatar picker failed " << dumpResponse() << llendl; } } }; diff --git a/indra/newview/llfloaterbuycurrencyhtml.cpp b/indra/newview/llfloaterbuycurrencyhtml.cpp index 013cf74c7b..6e641e7d40 100644 --- a/indra/newview/llfloaterbuycurrencyhtml.cpp +++ b/indra/newview/llfloaterbuycurrencyhtml.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llfloaterbuycurrencyhtml.h" +#include "llhttpconstants.h" #include "llstatusbar.h" //////////////////////////////////////////////////////////////////////////////// @@ -85,7 +86,7 @@ void LLFloaterBuyCurrencyHTML::navigateToFinalURL() llinfos << "Buy currency HTML parsed URL is " << buy_currency_url << llendl; // kick off the navigation - mBrowser->navigateTo( buy_currency_url, "text/html" ); + mBrowser->navigateTo( buy_currency_url, HTTP_CONTENT_TEXT_HTML ); } //////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llfloaterhelpbrowser.cpp b/indra/newview/llfloaterhelpbrowser.cpp index 4cb632bd6a..c0bb213540 100644 --- a/indra/newview/llfloaterhelpbrowser.cpp +++ b/indra/newview/llfloaterhelpbrowser.cpp @@ -29,6 +29,7 @@ #include "llfloaterhelpbrowser.h" #include "llfloaterreg.h" +#include "llhttpconstants.h" #include "llpluginclassmedia.h" #include "llmediactrl.h" #include "llviewerwindow.h" @@ -37,7 +38,6 @@ #include "llui.h" #include "llurlhistory.h" -#include "llmediactrl.h" #include "llviewermedia.h" #include "llviewerhelp.h" @@ -148,7 +148,7 @@ void LLFloaterHelpBrowser::openMedia(const std::string& media_url) { // explicitly make the media mime type for this floater since it will // only ever display one type of content (Web). - mBrowser->setHomePageUrl(media_url, "text/html"); - mBrowser->navigateTo(media_url, "text/html"); + mBrowser->setHomePageUrl(media_url, HTTP_CONTENT_TEXT_HTML); + mBrowser->navigateTo(media_url, HTTP_CONTENT_TEXT_HTML); setCurrentURL(media_url); } diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index c9f5b42b20..c365666f00 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -5839,7 +5839,7 @@ void LLFloaterModelPreview::handleModelPhysicsFeeReceived() mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty()); } -void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) +void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason) { llwarns << "LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(" << status << " : " << reason << ")" << llendl; doOnIdleOneTime(boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this, true)); @@ -5915,7 +5915,7 @@ void LLFloaterModelPreview::onPermissionsReceived(const LLSD& result) getChild("warning_message")->setVisible(!mHasUploadPerm); } -void LLFloaterModelPreview::setPermissonsErrorStatus(U32 status, const std::string& reason) +void LLFloaterModelPreview::setPermissonsErrorStatus(S32 status, const std::string& reason) { llwarns << "LLFloaterModelPreview::setPermissonsErrorStatus(" << status << " : " << reason << ")" << llendl; diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index e588418f7b..6c0c60b87f 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -200,11 +200,11 @@ public: /*virtual*/ void onPermissionsReceived(const LLSD& result); // called when error occurs during permissions request - /*virtual*/ void setPermissonsErrorStatus(U32 status, const std::string& reason); + /*virtual*/ void setPermissonsErrorStatus(S32 status, const std::string& reason); /*virtual*/ void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url); void handleModelPhysicsFeeReceived(); - /*virtual*/ void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason); + /*virtual*/ void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason); /*virtual*/ void onModelUploadSuccess(); diff --git a/indra/newview/llfloatermodeluploadbase.cpp b/indra/newview/llfloatermodeluploadbase.cpp index 6d3800bfa4..9f1fc06e14 100644 --- a/indra/newview/llfloatermodeluploadbase.cpp +++ b/indra/newview/llfloatermodeluploadbase.cpp @@ -45,7 +45,7 @@ void LLFloaterModelUploadBase::requestAgentUploadPermissions() if (!url.empty()) { llinfos<< typeid(*this).name() <<"::requestAgentUploadPermissions() requesting for upload model permissions from: "<< url <appendText( @@ -100,8 +105,10 @@ namespace } /*virtual*/ - void result(const LLSD& content) + void httpSuccess() { + const LLSD& content = getContent(); + LL_DEBUGS("Console") << content << LL_ENDL; if (mOutput) { mOutput->appendText( @@ -109,6 +116,7 @@ namespace } } + public: LLTextEditor * mOutput; }; diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 4a9ea5acf0..6c0e91dd2c 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -754,12 +754,12 @@ bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const L class ConsoleRequestResponder : public LLHTTPClient::Responder { -public: + LOG_CLASS(ConsoleRequestResponder); +protected: /*virtual*/ - void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + void httpFailure() { - llwarns << "ConsoleRequestResponder error requesting mesh_rez_enabled [status:" - << status << "]: " << content << llendl; + llwarns << "error requesting mesh_rez_enabled " << dumpResponse() << llendl; } }; @@ -767,12 +767,12 @@ public: // called if this request times out. class ConsoleUpdateResponder : public LLHTTPClient::Responder { -public: + LOG_CLASS(ConsoleUpdateResponder); +protected: /* virtual */ - void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + void httpFailure() { - llwarns << "ConsoleRequestResponder error updating mesh enabled region setting [status:" - << status << "]: " << content << llendl; + llwarns << "error updating mesh enabled region setting " << dumpResponse() << llendl; } }; @@ -2191,14 +2191,16 @@ void LLPanelEstateInfo::getEstateOwner() class LLEstateChangeInfoResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLEstateChangeInfoResponder); public: LLEstateChangeInfoResponder(LLPanelEstateInfo* panel) { mpPanel = panel->getHandle(); } +protected: // if we get a normal response, handle it here - virtual void result(const LLSD& content) + virtual void httpSuccess() { LL_INFOS("Windlight") << "Successfully committed estate info" << llendl; @@ -2209,10 +2211,9 @@ public: } // if we get an error response - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + virtual void httpFailure() { - llinfos << "LLEstateChangeInfoResponder::error [status:" - << status << "]: " << content << llendl; + LL_WARNS("Windlight") << dumpResponse() << LL_ENDL; } private: LLHandle mpPanel; diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 685b566fa8..f7fca90ebd 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -692,16 +692,18 @@ public: class LLUserReportResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLUserReportResponder); public: LLUserReportResponder(): LLHTTPClient::Responder() {} - void errorWithContent(U32 status, const std::string& reason, const LLSD& content) - { - // *TODO do some user messaging here - LLUploadDialog::modalUploadFinished(); - } - void result(const LLSD& content) +private: + void httpCompleted() { + if (!isGoodStatus()) + { + // *TODO do some user messaging here + LL_WARNS("UserReport") << dumpResponse() << LL_ENDL; + } // we don't care about what the server returns LLUploadDialog::modalUploadFinished(); } diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index 17c34f1da0..7e94784751 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -183,8 +183,14 @@ void LLPanelScriptLimitsInfo::updateChild(LLUICtrl* child_ctr) // Responders ///---------------------------------------------------------------------------- -void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content) +void fetchScriptLimitsRegionInfoResponder::httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } //we don't need to test with a fake respose here (shouldn't anyway) #ifdef DUMP_REPLIES_TO_LLINFOS @@ -221,13 +227,14 @@ void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content) } } -void fetchScriptLimitsRegionInfoResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void fetchScriptLimitsRegionInfoResponder::httpFailure() { - llwarns << "fetchScriptLimitsRegionInfoResponder error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; } -void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref) +void fetchScriptLimitsRegionSummaryResponder::httpSuccess() { + const LLSD& content_ref = getContent(); #ifdef USE_FAKE_RESPONSES LLSD fake_content; @@ -268,6 +275,12 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref) #endif + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + #ifdef DUMP_REPLIES_TO_LLINFOS @@ -291,7 +304,7 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref) LLTabContainer* tab = instance->getChild("scriptlimits_panels"); if(tab) { - LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild("script_limits_region_memory_panel"); + LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild("script_limits_region_memory_panel"); if(panel_memory) { panel_memory->getChild("loading_text")->setValue(LLSD(std::string(""))); @@ -301,20 +314,21 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref) { btn->setEnabled(true); } - - panel_memory->setRegionSummary(content); - } -} + + panel_memory->setRegionSummary(content); + } + } } } -void fetchScriptLimitsRegionSummaryResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void fetchScriptLimitsRegionSummaryResponder::httpFailure() { - llwarns << "fetchScriptLimitsRegionSummaryResponder error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; } -void fetchScriptLimitsRegionDetailsResponder::result(const LLSD& content_ref) +void fetchScriptLimitsRegionDetailsResponder::httpSuccess() { + const LLSD& content_ref = getContent(); #ifdef USE_FAKE_RESPONSES /* Updated detail service, ** denotes field added: @@ -377,6 +391,12 @@ result (map) #endif + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + #ifdef DUMP_REPLIES_TO_LLINFOS LLSDNotationStreamer notation_streamer(content); @@ -417,13 +437,14 @@ result (map) } } -void fetchScriptLimitsRegionDetailsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void fetchScriptLimitsRegionDetailsResponder::httpFailure() { - llwarns << "fetchScriptLimitsRegionDetailsResponder error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; } -void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref) +void fetchScriptLimitsAttachmentInfoResponder::httpSuccess() { + const LLSD& content_ref = getContent(); #ifdef USE_FAKE_RESPONSES @@ -465,6 +486,12 @@ void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref) #endif + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + #ifdef DUMP_REPLIES_TO_LLINFOS LLSDNotationStreamer notation_streamer(content); @@ -513,9 +540,9 @@ void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref) } } -void fetchScriptLimitsAttachmentInfoResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void fetchScriptLimitsAttachmentInfoResponder::httpFailure() { - llwarns << "fetchScriptLimitsAttachmentInfoResponder error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; } ///---------------------------------------------------------------------------- @@ -586,7 +613,7 @@ void LLPanelScriptLimitsRegionMemory::setParcelID(const LLUUID& parcel_id) } // virtual -void LLPanelScriptLimitsRegionMemory::setErrorStatus(U32 status, const std::string& reason) +void LLPanelScriptLimitsRegionMemory::setErrorStatus(S32 status, const std::string& reason) { llwarns << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<navigateTo(url, "text/html"); + mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML); } diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index a242b224cd..0613ffc94d 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -36,7 +36,7 @@ #include "llbutton.h" #include "llevents.h" #include "llhttpclient.h" -#include "llhttpstatuscodes.h" // for HTTP_FOUND +#include "llhttpconstants.h" #include "llnotificationsutil.h" #include "llradiogroup.h" #include "lltextbox.h" @@ -62,42 +62,46 @@ LLFloaterTOS::LLFloaterTOS(const LLSD& data) // on parent class indicating if the web server is working or not class LLIamHere : public LLHTTPClient::Responder { - private: - LLIamHere( LLFloaterTOS* parent ) : - mParent( parent ) - {} + LOG_CLASS(LLIamHere); +private: + LLIamHere( LLFloaterTOS* parent ) : + mParent( parent ) + {} - LLFloaterTOS* mParent; + LLFloaterTOS* mParent; - public: - - static LLIamHere* build( LLFloaterTOS* parent ) - { - return new LLIamHere( parent ); - }; - - virtual void setParent( LLFloaterTOS* parentIn ) - { - mParent = parentIn; - }; - - virtual void result( const LLSD& content ) +public: + static LLIamHere* build( LLFloaterTOS* parent ) + { + return new LLIamHere( parent ); + } + + virtual void setParent( LLFloaterTOS* parentIn ) + { + mParent = parentIn; + } + +protected: + virtual void httpSuccess() + { + if ( mParent ) { - if ( mParent ) - mParent->setSiteIsAlive( true ); - }; + mParent->setSiteIsAlive( true ); + } + } - virtual void error( U32 status, const std::string& reason ) + virtual void httpFailure() + { + LL_DEBUGS("LLIamHere") << dumpResponse() << LL_ENDL; + if ( mParent ) { - if ( mParent ) - { - // *HACK: For purposes of this alive check, 302 Found - // (aka Moved Temporarily) is considered alive. The web site - // redirects this link to a "cache busting" temporary URL. JC - bool alive = (status == HTTP_FOUND); - mParent->setSiteIsAlive( alive ); - } - }; + // *HACK: For purposes of this alive check, 302 Found + // (aka Moved Temporarily) is considered alive. The web site + // redirects this link to a "cache busting" temporary URL. JC + bool alive = (getStatus() == HTTP_FOUND); + mParent->setSiteIsAlive( alive ); + } + } }; // this is global and not a class member to keep crud out of the header file diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp index e85d849c9a..0751c830d5 100644 --- a/indra/newview/llfloaterurlentry.cpp +++ b/indra/newview/llfloaterurlentry.cpp @@ -48,31 +48,31 @@ static LLFloaterURLEntry* sInstance = NULL; // on the Panel Land Media and to discover the MIME type class LLMediaTypeResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLMediaTypeResponder); public: LLMediaTypeResponder( const LLHandle parent ) : - mParent( parent ) - {} - - LLHandle mParent; - - - virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content) - { - std::string media_type = content["content-type"].asString(); - std::string::size_type idx1 = media_type.find_first_of(";"); - std::string mime_type = media_type.substr(0, idx1); - completeAny(status, mime_type); - } - - void completeAny(U32 status, const std::string& mime_type) - { - // Set empty type to none/none. Empty string is reserved for legacy parcels - // which have no mime type set. - std::string resolved_mime_type = ! mime_type.empty() ? mime_type : LLMIMETypes::getDefaultMimeType(); - LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mParent.get(); - if ( floater_url_entry ) - floater_url_entry->headerFetchComplete( status, resolved_mime_type ); - } + mParent( parent ) + {} + + LLHandle mParent; + +private: + /* virtual */ void httpCompleted() + { + const bool check_lower = true; + const std::string& media_type = getResponseHeader(HTTP_HEADER_CONTENT_TYPE, check_lower); + std::string::size_type idx1 = media_type.find_first_of(";"); + std::string mime_type = media_type.substr(0, idx1); + + // Set empty type to none/none. Empty string is reserved for legacy parcels + // which have no mime type set. + std::string resolved_mime_type = ! mime_type.empty() ? mime_type : LLMIMETypes::getDefaultMimeType(); + LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mParent.get(); + if ( floater_url_entry ) + { + floater_url_entry->headerFetchComplete( getStatus(), resolved_mime_type ); + } + } }; //----------------------------------------------------------------------------- @@ -136,7 +136,7 @@ void LLFloaterURLEntry::buildURLHistory() } } -void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_type) +void LLFloaterURLEntry::headerFetchComplete(S32 status, const std::string& mime_type) { LLPanelLandMedia* panel_media = dynamic_cast(mPanelLandMediaHandle.get()); if (panel_media) diff --git a/indra/newview/llfloaterurlentry.h b/indra/newview/llfloaterurlentry.h index dfb49fe5ac..bdd1ebe592 100644 --- a/indra/newview/llfloaterurlentry.h +++ b/indra/newview/llfloaterurlentry.h @@ -40,7 +40,7 @@ public: // that panel via the handle. static LLHandle show(LLHandle panel_land_media_handle, const std::string media_url); /*virtual*/ BOOL postBuild(); - void headerFetchComplete(U32 status, const std::string& mime_type); + void headerFetchComplete(S32 status, const std::string& mime_type); bool addURLToCombobox(const std::string& media_url); diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 3fe2518de6..21b171446f 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -29,6 +29,7 @@ #include "llcombobox.h" #include "lliconctrl.h" #include "llfloaterreg.h" +#include "llhttpconstants.h" #include "lllayoutstack.h" #include "llpluginclassmedia.h" #include "llprogressbar.h" @@ -234,9 +235,9 @@ void LLFloaterWebContent::open_media(const Params& p) { // Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin. LLViewerMedia::proxyWindowOpened(p.target(), p.id()); - mWebBrowser->setHomePageUrl(p.url, "text/html"); + mWebBrowser->setHomePageUrl(p.url, HTTP_CONTENT_TEXT_HTML); mWebBrowser->setTarget(p.target); - mWebBrowser->navigateTo(p.url, "text/html"); + mWebBrowser->navigateTo(p.url, HTTP_CONTENT_TEXT_HTML); set_current_url(p.url); @@ -451,7 +452,7 @@ void LLFloaterWebContent::onEnterAddress() std::string url = mAddressCombo->getValue().asString(); if ( url.length() > 0 ) { - mWebBrowser->navigateTo( url, "text/html"); + mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML); }; } diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index cbd844cdac..472e3862ea 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -1843,23 +1843,31 @@ void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id, // Responder class for capability group management class GroupMemberDataResponder : public LLHTTPClient::Responder { + LOG_CLASS(GroupMemberDataResponder); public: - GroupMemberDataResponder() {} - virtual ~GroupMemberDataResponder() {} - virtual void result(const LLSD& pContent); - virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); + GroupMemberDataResponder() {} + virtual ~GroupMemberDataResponder() {} + private: - LLSD mMemberData; + /* virtual */ void httpSuccess(); + /* virtual */ void httpFailure(); + LLSD mMemberData; }; -void GroupMemberDataResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent) +void GroupMemberDataResponder::httpFailure() { - LL_WARNS("GrpMgr") << "Error receiving group member data [status:" - << pStatus << "]: " << pContent << LL_ENDL; + LL_WARNS("GrpMgr") << "Error receiving group member data " + << dumpResponse() << LL_ENDL; } -void GroupMemberDataResponder::result(const LLSD& content) +void GroupMemberDataResponder::httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } LLGroupMgr::processCapGroupMembersRequest(content); } diff --git a/indra/newview/llhomelocationresponder.cpp b/indra/newview/llhomelocationresponder.cpp index 37428c4a44..b1286cccf2 100644 --- a/indra/newview/llhomelocationresponder.cpp +++ b/indra/newview/llhomelocationresponder.cpp @@ -33,71 +33,76 @@ #include "llagent.h" #include "llviewerregion.h" -void LLHomeLocationResponder::result( const LLSD& content ) +void LLHomeLocationResponder::httpSuccess() { + const LLSD& content = getContent(); LLVector3 agent_pos; bool error = true; - + do { - + // was the call to /agent//home-location successful? // If not, we keep error set to true if( ! content.has("success") ) { break; } - + if( 0 != strncmp("true", content["success"].asString().c_str(), 4 ) ) { break; } - + // did the simulator return a "justified" home location? // If no, we keep error set to true if( ! content.has( "HomeLocation" ) ) { break; } - + if( ! content["HomeLocation"].has("LocationPos") ) { break; } - + if( ! content["HomeLocation"]["LocationPos"].has("X") ) { break; } agent_pos.mV[VX] = content["HomeLocation"]["LocationPos"]["X"].asInteger(); - + if( ! content["HomeLocation"]["LocationPos"].has("Y") ) { break; } agent_pos.mV[VY] = content["HomeLocation"]["LocationPos"]["Y"].asInteger(); - + if( ! content["HomeLocation"]["LocationPos"].has("Z") ) { break; } agent_pos.mV[VZ] = content["HomeLocation"]["LocationPos"]["Z"].asInteger(); - + error = false; } while( 0 ); - - if( ! error ) + + if( error ) + { + failureResult(HTTP_INTERNAL_ERROR, "Invalid server response content", content); + } + else { llinfos << "setting home position" << llendl; - + LLViewerRegion *viewer_region = gAgent.getRegion(); gAgent.setHomePosRegion( viewer_region->getHandle(), agent_pos ); } } -void LLHomeLocationResponder::errorWithContent( U32 status, const std::string& reason, const LLSD& content ) +void LLHomeLocationResponder::httpFailure() { - llwarns << "LLHomeLocationResponder error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; } diff --git a/indra/newview/llhomelocationresponder.h b/indra/newview/llhomelocationresponder.h index 9bf4b12c4e..adc6c8cb58 100644 --- a/indra/newview/llhomelocationresponder.h +++ b/indra/newview/llhomelocationresponder.h @@ -35,8 +35,10 @@ /* Typedef, Enum, Class, Struct, etc. */ class LLHomeLocationResponder : public LLHTTPClient::Responder { - virtual void result( const LLSD& content ); - virtual void errorWithContent( U32 status, const std::string& reason, const LLSD& content ); + LOG_CLASS(LLHomeLocationResponder); +private: + /* virtual */ void httpSuccess(); + /* virtual */ void httpFailure(); }; #endif diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index fff178f8fe..c933d5428d 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -979,16 +979,17 @@ BOOL LLIMFloater::isInviteAllowed() const class LLSessionInviteResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLSessionInviteResponder); public: LLSessionInviteResponder(const LLUUID& session_id) { mSessionID = session_id; } - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) +protected: + void httpFailure() { - llwarns << "Error inviting all agents to session [status:" - << statusNum << "]: " << content << llendl; + llwarns << "Error inviting all agents to session " << dumpResponse() << llendl; //throw something back to the viewer here? } diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 1dab0e67bf..95ede326e6 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -388,16 +388,17 @@ void LLFloaterIMPanel::draw() class LLSessionInviteResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLSessionInviteResponder); public: LLSessionInviteResponder(const LLUUID& session_id) { mSessionID = session_id; } - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) +protected: + void httpFailure() { - llwarns << "Error inviting all agents to session [status:" - << statusNum << "]: " << content << llendl; + llwarns << "Error inviting all agents to session " << dumpResponse() << llendl; //throw something back to the viewer here? } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 20b33c5d08..a00de8eb26 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -1214,6 +1214,7 @@ void start_deprecated_conference_chat( class LLStartConferenceChatResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLStartConferenceChatResponder); public: LLStartConferenceChatResponder( const LLUUID& temp_session_id, @@ -1227,10 +1228,12 @@ public: mAgents = agents_to_invite; } - virtual void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) +protected: + virtual void httpFailure() { //try an "old school" way. - if ( statusNum == 400 ) + // *TODO: What about other error status codes? 4xx 5xx? + if ( getStatus() == HTTP_BAD_REQUEST ) { start_deprecated_conference_chat( mTempSessionID, @@ -1239,8 +1242,7 @@ public: mAgents); } - llwarns << "LLStartConferenceChatResponder error [status:" - << statusNum << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; //else throw an error back to the client? //in theory we should have just have these error strings @@ -1332,6 +1334,7 @@ bool LLIMModel::sendStartSession( class LLViewerChatterBoxInvitationAcceptResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLViewerChatterBoxInvitationAcceptResponder); public: LLViewerChatterBoxInvitationAcceptResponder( const LLUUID& session_id, @@ -1341,8 +1344,15 @@ public: mInvitiationType = invitation_type; } - void result(const LLSD& content) +private: + void httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } if ( gIMMgr) { LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); @@ -1387,19 +1397,17 @@ public: } } - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) + void httpFailure() { - llwarns << "LLViewerChatterBoxInvitationAcceptResponder error [status:" - << statusNum << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; //throw something back to the viewer here? if ( gIMMgr ) { gIMMgr->clearPendingAgentListUpdates(mSessionID); gIMMgr->clearPendingInvitation(mSessionID); - if ( 404 == statusNum ) + if ( HTTP_NOT_FOUND == getStatus() ) { - std::string error_string; - error_string = "session_does_not_exist_error"; + static const std::string error_string("session_does_not_exist_error"); gIMMgr->showSessionStartError(error_string, mSessionID); } } diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index aafc43b02d..1f719a22ef 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -495,21 +495,23 @@ void LLInspectAvatar::toggleSelectedVoice(bool enabled) class MuteVoiceResponder : public LLHTTPClient::Responder { + LOG_CLASS(MuteVoiceResponder); public: MuteVoiceResponder(const LLUUID& session_id) { mSessionID = session_id; } - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + protected: + virtual void httpFailure() { - llwarns << "MuteVoiceResponder error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; if ( gIMMgr ) { //403 == you're not a mod //should be disabled if you're not a moderator - if ( 403 == status ) + if ( HTTP_FORBIDDEN == getStatus() ) { gIMMgr->showSessionEventError( "mute", 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(); } diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index dfdd237c95..9c2ca8cae9 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -81,11 +81,12 @@ public: class fetchInventoryResponder : public LLHTTPClient::Responder { + LOG_CLASS(fetchInventoryResponder); public: fetchInventoryResponder(const LLSD& request_sd) : mRequestSD(request_sd) {}; - void result(const LLSD& content); - void errorWithContent(U32 status, const std::string& reason, const LLSD& content); protected: + virtual void httpSuccess(); + virtual void httpFailure(); LLSD mRequestSD; }; diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index f2b39e7186..e1537033f9 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -363,35 +363,39 @@ void LLInventoryModelBackgroundFetch::incrFetchCount(S16 fetching) class LLInventoryModelFetchItemResponder : public LLInventoryModel::fetchInventoryResponder { + LOG_CLASS(LLInventoryModelFetchItemResponder); public: LLInventoryModelFetchItemResponder(const LLSD& request_sd) : LLInventoryModel::fetchInventoryResponder(request_sd) {}; - void result(const LLSD& content); - void errorWithContent(U32 status, const std::string& reason, const LLSD& content); +private: + /* virtual */ void httpSuccess(); + /* virtual */ void httpFailure(); }; -void LLInventoryModelFetchItemResponder::result( const LLSD& content ) +void LLInventoryModelFetchItemResponder::httpSuccess() { - LLInventoryModel::fetchInventoryResponder::result(content); + LLInventoryModel::fetchInventoryResponder::httpSuccess(); LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); } -void LLInventoryModelFetchItemResponder::errorWithContent( U32 status, const std::string& reason, const LLSD& content ) +void LLInventoryModelFetchItemResponder::httpFailure() { - LLInventoryModel::fetchInventoryResponder::errorWithContent(status, reason, content); + LLInventoryModel::fetchInventoryResponder::httpFailure(); LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); } class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder { + LOG_CLASS(LLInventoryModelFetchDescendentsResponder); public: LLInventoryModelFetchDescendentsResponder(const LLSD& request_sd, uuid_vec_t recursive_cats) : mRequestSD(request_sd), mRecursiveCatUUIDs(recursive_cats) {}; //LLInventoryModelFetchDescendentsResponder() {}; - void result(const LLSD& content); - void errorWithContent(U32 status, const std::string& reason, const LLSD& content); +private: + /* virtual */ void httpSuccess(); + /* virtual */ void httpFailure(); protected: BOOL getIsRecursive(const LLUUID& cat_id) const; private: @@ -400,8 +404,14 @@ private: }; // If we get back a normal response, handle it here. -void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content) +void LLInventoryModelFetchDescendentsResponder::httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); if (content.has("folders")) { @@ -508,11 +518,12 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content) for(LLSD::array_const_iterator folder_it = content["bad_folders"].beginArray(); folder_it != content["bad_folders"].endArray(); ++folder_it) - { + { + // *TODO: Stop copying data LLSD folder_sd = *folder_it; // These folders failed on the dataserver. We probably don't want to retry them. - llinfos << "Folder " << folder_sd["folder_id"].asString() + llwarns << "Folder " << folder_sd["folder_id"].asString() << "Error: " << folder_sd["error"].asString() << llendl; } } @@ -529,21 +540,19 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content) } // If we get back an error (not found, etc...), handle it here. -void LLInventoryModelFetchDescendentsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLInventoryModelFetchDescendentsResponder::httpFailure() { + llwarns << dumpResponse() << llendl; LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); - llinfos << "LLInventoryModelFetchDescendentsResponder::error [status:" - << status << "]: " << content << llendl; - fetcher->incrFetchCount(-1); - if (status==499) // timed out + if (getStatus()==HTTP_INTERNAL_ERROR) // timed out or curl failure { for(LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray(); folder_it != mRequestSD["folders"].endArray(); ++folder_it) - { + { LLSD folder_sd = *folder_it; LLUUID folder_id = folder_sd["folder_id"]; const BOOL recursive = getIsRecursive(folder_id); diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index 0b009b68f7..bea1d62b93 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -99,7 +99,7 @@ namespace LLMarketplaceImport bool hasSessionCookie(); bool inProgress(); bool resultPending(); - U32 getResultStatus(); + S32 getResultStatus(); const LLSD& getResults(); bool establishMarketplaceSessionCookie(); @@ -113,7 +113,7 @@ namespace LLMarketplaceImport static bool sImportInProgress = false; static bool sImportPostPending = false; static bool sImportGetPending = false; - static U32 sImportResultStatus = 0; + static S32 sImportResultStatus = 0; static LLSD sImportResults = LLSD::emptyMap(); static LLTimer slmGetTimer; @@ -123,22 +123,22 @@ namespace LLMarketplaceImport class LLImportPostResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLImportPostResponder); public: LLImportPostResponder() : LLCurl::Responder() {} - - void completed(U32 status, const std::string& reason, const LLSD& content) + + protected: + /* virtual */ void httpCompleted() { slmPostTimer.stop(); if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - llinfos << " SLM POST status: " << status << llendl; - llinfos << " SLM POST reason: " << reason << llendl; - llinfos << " SLM POST content: " << content.asString() << llendl; - - llinfos << " SLM POST timer: " << slmPostTimer.getElapsedTimeF32() << llendl; + llinfos << " SLM [timer:" << slmPostTimer.getElapsedTimeF32() << "] " + << dumpResponse() << llendl; } + S32 status = getStatus(); if ((status == MarketplaceErrorCodes::IMPORT_REDIRECT) || (status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) || (status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT)) @@ -154,38 +154,36 @@ namespace LLMarketplaceImport sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_DONE); sImportPostPending = false; sImportResultStatus = status; - sImportId = content; + sImportId = getContent(); } }; class LLImportGetResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLImportGetResponder); public: LLImportGetResponder() : LLCurl::Responder() {} - void completedHeader(U32 status, const std::string& reason, const LLSD& content) + protected: + /* virtual */ void httpCompleted() { - const std::string& set_cookie_string = content["set-cookie"].asString(); + const bool check_lower = true; + const std::string& set_cookie_string = getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower); if (!set_cookie_string.empty()) { sMarketplaceCookie = set_cookie_string; } - } - - void completed(U32 status, const std::string& reason, const LLSD& content) - { + slmGetTimer.stop(); if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - llinfos << " SLM GET status: " << status << llendl; - llinfos << " SLM GET reason: " << reason << llendl; - llinfos << " SLM GET content: " << content.asString() << llendl; - - llinfos << " SLM GET timer: " << slmGetTimer.getElapsedTimeF32() << llendl; + llinfos << " SLM [timer:" << slmGetTimer.getElapsedTimeF32() << "] " + << dumpResponse() << llendl; } + S32 status = getStatus(); if ((status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) || (status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT)) { @@ -200,7 +198,7 @@ namespace LLMarketplaceImport sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING); sImportGetPending = false; sImportResultStatus = status; - sImportResults = content; + sImportResults = getContent(); } }; @@ -221,7 +219,7 @@ namespace LLMarketplaceImport return (sImportPostPending || sImportGetPending); } - U32 getResultStatus() + S32 getResultStatus() { return sImportResultStatus; } @@ -280,10 +278,10 @@ namespace LLMarketplaceImport // Make the headers for the post LLSD headers = LLSD::emptyMap(); - headers["Accept"] = "*/*"; - headers["Cookie"] = sMarketplaceCookie; - headers["Content-Type"] = "application/llsd+xml"; - headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent(); + headers[HTTP_HEADER_ACCEPT] = "*/*"; + headers[HTTP_HEADER_COOKIE] = sMarketplaceCookie; + headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML; + headers[HTTP_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent(); if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { @@ -313,11 +311,12 @@ namespace LLMarketplaceImport // Make the headers for the post LLSD headers = LLSD::emptyMap(); - headers["Accept"] = "*/*"; - headers["Connection"] = "Keep-Alive"; - headers["Cookie"] = sMarketplaceCookie; - headers["Content-Type"] = "application/xml"; - headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent(); + headers[HTTP_HEADER_ACCEPT] = "*/*"; + headers[HTTP_HEADER_CONNECTION] = "Keep-Alive"; + headers[HTTP_HEADER_COOKIE] = sMarketplaceCookie; + // *TODO: Should this be 'application/llsd+xml'? + headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML; + headers[HTTP_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent(); if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 2075aeed63..cb5640b4da 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -52,6 +52,7 @@ #include "llsdutil.h" #include "lllayoutstack.h" #include "lliconctrl.h" +#include "llhttpconstants.h" #include "lltextbox.h" #include "llbutton.h" #include "llcheckboxctrl.h" @@ -576,7 +577,7 @@ void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::str { mCurrentNavUrl = expanded_filename; mMediaSource->setSize(mTextureWidth, mTextureHeight); - mMediaSource->navigateTo(expanded_filename, "text/html", false); + mMediaSource->navigateTo(expanded_filename, HTTP_CONTENT_TEXT_HTML, false); } } @@ -948,7 +949,7 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_ERROR_PAGE" << LL_ENDL; if ( mErrorPageURL.length() > 0 ) { - navigateTo(mErrorPageURL, "text/html"); + navigateTo(mErrorPageURL, HTTP_CONTENT_TEXT_HTML); }; }; break; diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index e3b46d5d2f..bc1aa087e5 100644 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -35,7 +35,7 @@ #include -#include "llhttpstatuscodes.h" +#include "llhttpconstants.h" #include "llsdutil.h" #include "llmediaentry.h" #include "lltextureentry.h" @@ -564,7 +564,7 @@ LLMediaDataClient::Responder::Responder(const request_ptr_t &request) } /*virtual*/ -void LLMediaDataClient::Responder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLMediaDataClient::Responder::httpFailure() { mRequest->stopTracking(); @@ -574,9 +574,17 @@ void LLMediaDataClient::Responder::errorWithContent(U32 status, const std::strin return; } - if (status == HTTP_SERVICE_UNAVAILABLE) + if (getStatus() == HTTP_SERVICE_UNAVAILABLE) { - F32 retry_timeout = mRequest->getRetryTimerDelay(); + F32 retry_timeout; +#if 0 + // *TODO: Honor server Retry-After header. + if (!hasResponseHeader(HTTP_HEADER_RETRY_AFTER) + || !getSecondsUntilRetryAfter(getResponseHeader(HTTP_HEADER_RETRY_AFTER), retry_timeout)) +#endif + { + retry_timeout = mRequest->getRetryTimerDelay(); + } mRequest->incRetryCount(); @@ -594,15 +602,16 @@ void LLMediaDataClient::Responder::errorWithContent(U32 status, const std::strin << mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL; } } + // *TODO: Redirect on 3xx status codes. else { - LL_WARNS("LLMediaDataClient") << *mRequest << " http error [status:" - << status << "]:" << content << ")" << LL_ENDL; + LL_WARNS("LLMediaDataClient") << *mRequest << " http failure " + << dumpResponse() << LL_ENDL; } } /*virtual*/ -void LLMediaDataClient::Responder::result(const LLSD& content) +void LLMediaDataClient::Responder::httpSuccess() { mRequest->stopTracking(); @@ -612,7 +621,7 @@ void LLMediaDataClient::Responder::result(const LLSD& content) return; } - LL_DEBUGS("LLMediaDataClientResponse") << *mRequest << " result : " << ll_print_sd(content) << LL_ENDL; + LL_DEBUGS("LLMediaDataClientResponse") << *mRequest << " " << dumpResponse() << LL_ENDL; } ////////////////////////////////////////////////////////////////////////////////////// @@ -876,7 +885,7 @@ LLMediaDataClient::Responder *LLObjectMediaDataClient::RequestUpdate::createResp /*virtual*/ -void LLObjectMediaDataClient::Responder::result(const LLSD& content) +void LLObjectMediaDataClient::Responder::httpSuccess() { getRequest()->stopTracking(); @@ -886,10 +895,16 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content) return; } + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + // This responder is only used for GET requests, not UPDATE. + LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " " << dumpResponse() << LL_ENDL; - LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " GET returned: " << ll_print_sd(content) << LL_ENDL; - // Look for an error if (content.has("error")) { @@ -1003,7 +1018,7 @@ LLMediaDataClient::Responder *LLObjectMediaNavigateClient::RequestNavigate::crea } /*virtual*/ -void LLObjectMediaNavigateClient::Responder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLObjectMediaNavigateClient::Responder::httpFailure() { getRequest()->stopTracking(); @@ -1015,14 +1030,14 @@ void LLObjectMediaNavigateClient::Responder::errorWithContent(U32 status, const // Bounce back (unless HTTP_SERVICE_UNAVAILABLE, in which case call base // class - if (status == HTTP_SERVICE_UNAVAILABLE) + if (getStatus() == HTTP_SERVICE_UNAVAILABLE) { - LLMediaDataClient::Responder::errorWithContent(status, reason, content); + LLMediaDataClient::Responder::httpFailure(); } else { // bounce the face back - LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: http code=" << status << LL_ENDL; + LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: " << dumpResponse() << LL_ENDL; const LLSD &payload = getRequest()->getPayload(); // bounce the face back getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]); @@ -1030,7 +1045,7 @@ void LLObjectMediaNavigateClient::Responder::errorWithContent(U32 status, const } /*virtual*/ -void LLObjectMediaNavigateClient::Responder::result(const LLSD& content) +void LLObjectMediaNavigateClient::Responder::httpSuccess() { getRequest()->stopTracking(); @@ -1040,8 +1055,9 @@ void LLObjectMediaNavigateClient::Responder::result(const LLSD& content) return; } - LL_INFOS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << ll_print_sd(content) << LL_ENDL; + LL_INFOS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << dumpResponse() << LL_ENDL; + const LLSD& content = getContent(); if (content.has("error")) { const LLSD &error = content["error"]; @@ -1065,6 +1081,6 @@ void LLObjectMediaNavigateClient::Responder::result(const LLSD& content) else { // No action required. - LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " result : " << ll_print_sd(content) << LL_ENDL; + LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " " << dumpResponse() << LL_ENDL; } } diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h index 89e20a28d0..231b883c32 100644 --- a/indra/newview/llmediadataclient.h +++ b/indra/newview/llmediadataclient.h @@ -74,8 +74,9 @@ public: // Abstracts the Cap URL, the request, and the responder class LLMediaDataClient : public LLRefCount { -public: +protected: LOG_CLASS(LLMediaDataClient); +public: const static F32 QUEUE_TIMER_DELAY;// = 1.0; // seconds(s) const static F32 UNAVAILABLE_RETRY_TIMER_DELAY;// = 5.0; // secs @@ -192,14 +193,16 @@ protected: // Responder class Responder : public LLHTTPClient::Responder { + LOG_CLASS(Responder); public: Responder(const request_ptr_t &request); + request_ptr_t &getRequest() { return mRequest; } + + protected: //If we get back an error (not found, etc...), handle it here - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); + virtual void httpFailure(); //If we get back a normal response, handle it here. Default just logs it. - virtual void result(const LLSD& content); - - request_ptr_t &getRequest() { return mRequest; } + virtual void httpSuccess(); private: request_ptr_t mRequest; @@ -287,8 +290,9 @@ private: // MediaDataClient specific for the ObjectMedia cap class LLObjectMediaDataClient : public LLMediaDataClient { -public: +protected: LOG_CLASS(LLObjectMediaDataClient); +public: LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY, F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY, U32 max_retries = MAX_RETRIES, @@ -341,10 +345,12 @@ protected: class Responder : public LLMediaDataClient::Responder { + LOG_CLASS(Responder); public: Responder(const request_ptr_t &request) : LLMediaDataClient::Responder(request) {} - virtual void result(const LLSD &content); + protected: + virtual void httpSuccess(); }; private: // The Get/Update data client needs a second queue to avoid object updates starving load-ins. @@ -362,8 +368,9 @@ private: // MediaDataClient specific for the ObjectMediaNavigate cap class LLObjectMediaNavigateClient : public LLMediaDataClient { -public: +protected: LOG_CLASS(LLObjectMediaNavigateClient); +public: // NOTE: from llmediaservice.h static const int ERROR_PERMISSION_DENIED_CODE = 8002; @@ -397,11 +404,13 @@ protected: class Responder : public LLMediaDataClient::Responder { + LOG_CLASS(Responder); public: Responder(const request_ptr_t &request) : LLMediaDataClient::Responder(request) {} - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); - virtual void result(const LLSD &content); + protected: + virtual void httpFailure(); + virtual void httpSuccess(); private: void mediaNavigateBounceBack(); }; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 17311dd75e..1469dbc346 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -28,7 +28,7 @@ #include "apr_pools.h" #include "apr_dso.h" -#include "llhttpstatuscodes.h" +#include "llhttpconstants.h" #include "llmeshrepository.h" #include "llagent.h" @@ -202,6 +202,7 @@ U32 LLMeshRepoThread::sMaxConcurrentRequests = 1; class LLMeshHeaderResponder : public LLCurl::Responder { + LOG_CLASS(LLMeshHeaderResponder); public: LLVolumeParams mMeshParams; bool mProcessed; @@ -230,14 +231,14 @@ public: } } - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, + virtual void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer); }; class LLMeshLODResponder : public LLCurl::Responder { + LOG_CLASS(LLMeshLODResponder); public: LLVolumeParams mMeshParams; S32 mLOD; @@ -266,14 +267,14 @@ public: } } - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, + virtual void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer); }; class LLMeshSkinInfoResponder : public LLCurl::Responder { + LOG_CLASS(LLMeshSkinInfoResponder); public: LLUUID mMeshID; U32 mRequestedBytes; @@ -291,14 +292,14 @@ public: llassert(mProcessed); } - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, + virtual void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer); }; class LLMeshDecompositionResponder : public LLCurl::Responder { + LOG_CLASS(LLMeshDecompositionResponder); public: LLUUID mMeshID; U32 mRequestedBytes; @@ -316,14 +317,14 @@ public: llassert(mProcessed); } - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, + virtual void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer); }; class LLMeshPhysicsShapeResponder : public LLCurl::Responder { + LOG_CLASS(LLMeshPhysicsShapeResponder); public: LLUUID mMeshID; U32 mRequestedBytes; @@ -341,8 +342,7 @@ public: llassert(mProcessed); } - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, + virtual void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer); }; @@ -398,6 +398,7 @@ void log_upload_error(S32 status, const LLSD& content, std::string stage, std::s class LLWholeModelFeeResponder: public LLCurl::Responder { + LOG_CLASS(LLWholeModelFeeResponder); LLMeshUploadThread* mThread; LLSD mModelData; LLHandle mObserverHandle; @@ -421,21 +422,20 @@ public: } } - virtual void completed(U32 status, - const std::string& reason, - const LLSD& content) +protected: + virtual void httpCompleted() { - LLSD cc = content; + LLSD cc = getContent(); if (gSavedSettings.getS32("MeshUploadFakeErrors")&1) { cc = llsd_from_file("fake_upload_error.xml"); } - + dump_llsd_to_file(cc,make_dump_name("whole_model_fee_response_",dump_num)); LLWholeModelFeeObserver* observer = mObserverHandle.get(); - if (isGoodStatus(status) && + if (isGoodStatus() && cc["state"].asString() == "upload") { mThread->mWholeModelUploadURL = cc["uploader"].asString(); @@ -448,13 +448,14 @@ public: } else { - llwarns << "fee request failed" << llendl; + llwarns << "fee request failed " << dumpResponse() << llendl; + S32 status = getStatus(); log_upload_error(status,cc,"fee",mModelData["name"]); mThread->mWholeModelUploadURL = ""; if (observer) { - observer->setModelPhysicsFeeErrorStatus(status, reason); + observer->setModelPhysicsFeeErrorStatus(status, getReason()); } } } @@ -463,6 +464,7 @@ public: class LLWholeModelUploadResponder: public LLCurl::Responder { + LOG_CLASS(LLWholeModelUploadResponder); LLMeshUploadThread* mThread; LLSD mModelData; LLHandle mObserverHandle; @@ -487,11 +489,10 @@ public: } } - virtual void completed(U32 status, - const std::string& reason, - const LLSD& content) +protected: + virtual void httpCompleted() { - LLSD cc = content; + LLSD cc = getContent(); if (gSavedSettings.getS32("MeshUploadFakeErrors")&2) { cc = llsd_from_file("fake_upload_error.xml"); @@ -503,7 +504,7 @@ public: // requested "mesh" asset type isn't actually the type // of the resultant object, fix it up here. - if (isGoodStatus(status) && + if (isGoodStatus() && cc["state"].asString() == "complete") { mModelData["asset_type"] = "object"; @@ -516,9 +517,9 @@ public: } else { - llwarns << "upload failed" << llendl; + llwarns << "upload failed " << dumpResponse() << llendl; std::string model_name = mModelData["name"].asString(); - log_upload_error(status,cc,"upload",model_name); + log_upload_error(getStatus(),cc,"upload",model_name); if (observer) { @@ -807,7 +808,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) //reading from VFS failed for whatever reason, fetch from sim std::vector headers; - headers.push_back("Accept: application/octet-stream"); + headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) @@ -889,7 +890,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) //reading from VFS failed for whatever reason, fetch from sim std::vector headers; - headers.push_back("Accept: application/octet-stream"); + headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) @@ -970,7 +971,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) //reading from VFS failed for whatever reason, fetch from sim std::vector headers; - headers.push_back("Accept: application/octet-stream"); + headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) @@ -1051,7 +1052,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& c //either cache entry doesn't exist or is corrupt, request header from simulator bool retval = true ; std::vector headers; - headers.push_back("Accept: application/octet-stream"); + headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); std::string http_url = constructUrl(mesh_params.getSculptID()); if (!http_url.empty()) @@ -1126,7 +1127,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, //reading from VFS failed for whatever reason, fetch from sim std::vector headers; - headers.push_back("Accept: application/octet-stream"); + headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) @@ -1898,10 +1899,10 @@ void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header) } -void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) +void LLMeshLODResponder::completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) { + S32 status = getStatus(); mProcessed = true; // thread could have already be destroyed during logout @@ -1912,14 +1913,15 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, S32 data_size = buffer->countAfter(channels.in(), NULL); + // *TODO: What about 3xx redirect codes? What about status 400 (Bad Request)? if (status < 200 || status > 400) { - llwarns << status << ": " << reason << llendl; + llwarns << dumpResponse() << llendl; } if (data_size < mRequestedBytes) { - if (status == 499 || status == 503) + if (status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE) { //timeout or service unavailable, try again llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; @@ -1927,8 +1929,8 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, } else { - llassert(status == 499 || status == 503); //intentionally trigger a breakpoint - llwarns << "Unhandled status " << status << llendl; + llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint + llwarns << "Unhandled status " << dumpResponse() << llendl; } return; } @@ -1962,10 +1964,10 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, delete [] data; } -void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) +void LLMeshSkinInfoResponder::completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) { + S32 status = getStatus(); mProcessed = true; // thread could have already be destroyed during logout @@ -1976,14 +1978,15 @@ void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason S32 data_size = buffer->countAfter(channels.in(), NULL); + // *TODO: What about 3xx redirect codes? What about status 400 (Bad Request)? if (status < 200 || status > 400) { - llwarns << status << ": " << reason << llendl; + llwarns << dumpResponse() << llendl; } if (data_size < mRequestedBytes) { - if (status == 499 || status == 503) + if (status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE) { //timeout or service unavailable, try again llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; @@ -1991,8 +1994,8 @@ void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason } else { - llassert(status == 499 || status == 503); //intentionally trigger a breakpoint - llwarns << "Unhandled status " << status << llendl; + llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint + llwarns << "Unhandled status " << dumpResponse() << llendl; } return; } @@ -2026,10 +2029,10 @@ void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason delete [] data; } -void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) +void LLMeshDecompositionResponder::completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) { + S32 status = getStatus(); mProcessed = true; if( !gMeshRepo.mThread ) @@ -2039,14 +2042,15 @@ void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& r S32 data_size = buffer->countAfter(channels.in(), NULL); + // *TODO: What about 3xx redirect codes? What about status 400 (Bad Request)? if (status < 200 || status > 400) { - llwarns << status << ": " << reason << llendl; + llwarns << dumpResponse() << llendl; } if (data_size < mRequestedBytes) { - if (status == 499 || status == 503) + if (status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE) { //timeout or service unavailable, try again llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; @@ -2054,8 +2058,8 @@ void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& r } else { - llassert(status == 499 || status == 503); //intentionally trigger a breakpoint - llwarns << "Unhandled status " << status << llendl; + llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint + llwarns << "Unhandled status " << dumpResponse() << llendl; } return; } @@ -2089,10 +2093,10 @@ void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& r delete [] data; } -void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) +void LLMeshPhysicsShapeResponder::completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) { + S32 status = getStatus(); mProcessed = true; // thread could have already be destroyed during logout @@ -2103,14 +2107,15 @@ void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& re S32 data_size = buffer->countAfter(channels.in(), NULL); + // *TODO: What about 3xx redirect codes? What about status 400 (Bad Request)? if (status < 200 || status > 400) { - llwarns << status << ": " << reason << llendl; + llwarns << dumpResponse() << llendl; } if (data_size < mRequestedBytes) { - if (status == 499 || status == 503) + if (status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE) { //timeout or service unavailable, try again llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; @@ -2118,8 +2123,8 @@ void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& re } else { - llassert(status == 499 || status == 503); //intentionally trigger a breakpoint - llwarns << "Unhandled status " << status << llendl; + llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint + llwarns << "Unhandled status " << dumpResponse() << llendl; } return; } @@ -2153,10 +2158,10 @@ void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& re delete [] data; } -void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) +void LLMeshHeaderResponder::completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) { + S32 status = getStatus(); mProcessed = true; // thread could have already be destroyed during logout @@ -2165,6 +2170,7 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, return; } + // *TODO: What about 3xx redirect codes? What about status 400 (Bad Request)? if (status < 200 || status > 400) { //llwarns @@ -2178,9 +2184,9 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, // and (somewhat more optional than the others) retries // again after some set period of time - llassert(status == 503 || status == 499); + llassert(status == HTTP_SERVICE_UNAVAILABLE || status == HTTP_INTERNAL_ERROR); - if (status == 503 || status == 499) + if (status == HTTP_SERVICE_UNAVAILABLE || status == HTTP_INTERNAL_ERROR) { //retry llwarns << "Timeout or service unavailable, retrying." << llendl; LLMeshRepository::sHTTPRetryCount++; @@ -2192,7 +2198,7 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, } else { - llwarns << "Unhandled status." << llendl; + llwarns << "Unhandled status " << dumpResponse() << llendl; } } @@ -2214,9 +2220,7 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, if (!success) { - llwarns - << "Unable to parse mesh header: " - << status << ": " << reason << llendl; + llwarns << "Unable to parse mesh header: " << dumpResponse() << llendl; } else if (data && data_size > 0) { diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 862e4be203..4f5e07c566 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -95,15 +95,11 @@ class LLClassifiedClickMessageResponder : public LLHTTPClient::Responder { LOG_CLASS(LLClassifiedClickMessageResponder); -public: +protected: // If we get back an error (not found, etc...), handle it here - virtual void errorWithContent( - U32 status, - const std::string& reason, - const LLSD& content) + virtual void httpFailure() { - llwarns << "Sending click message failed (" << status << "): [" << reason << "]" << llendl; - llwarns << "Content: [" << content << "]" << llendl; + llwarns << "Sending click message failed " << dumpResponse() << llendl; } }; diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index d6fccb9705..21b58dfbbf 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -529,7 +529,7 @@ void LLLandmarksPanel::setParcelID(const LLUUID& parcel_id) } // virtual -void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason) +void LLLandmarksPanel::setErrorStatus(S32 status, const std::string& reason) { llwarns << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<reshapeBrowser(); // *TODO: Append all the usual login parameters, like first_login=Y etc. std::string splash_screen_url = LLGridManager::getInstance()->getLoginPage(); - web_browser->navigateTo( splash_screen_url, "text/html" ); + web_browser->navigateTo( splash_screen_url, HTTP_CONTENT_TEXT_HTML ); LLUICtrl* username_combo = sInstance->getChild("username_combo"); username_combo->setFocus(TRUE); } @@ -791,7 +791,7 @@ void LLPanelLogin::loadLoginPage() if (web_browser->getCurrentNavUrl() != login_uri.asString()) { LL_DEBUGS("AppInit") << "loading: " << login_uri << LL_ENDL; - web_browser->navigateTo( login_uri.asString(), "text/html" ); + web_browser->navigateTo( login_uri.asString(), HTTP_CONTENT_TEXT_HTML ); } } diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h index 3c1f14759c..7a8bd66fcf 100644 --- a/indra/newview/llpanelpick.h +++ b/indra/newview/llpanelpick.h @@ -86,7 +86,7 @@ public: //This stuff we got from LLRemoteParcelObserver, in the last one we intentionally do nothing /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); /*virtual*/ void setParcelID(const LLUUID& parcel_id) { mParcelId = parcel_id; } - /*virtual*/ void setErrorStatus(U32 status, const std::string& reason) {}; + /*virtual*/ void setErrorStatus(S32 status, const std::string& reason) {}; protected: diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index 4ae0c0eb12..4e7c5f6ed2 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -169,15 +169,15 @@ void LLPanelPlaceInfo::displayParcelInfo(const LLUUID& region_id, } // virtual -void LLPanelPlaceInfo::setErrorStatus(U32 status, const std::string& reason) +void LLPanelPlaceInfo::setErrorStatus(S32 status, const std::string& reason) { // We only really handle 404 and 499 errors std::string error_text; - if(status == 404) + if(status == HTTP_NOT_FOUND) { error_text = getString("server_error_text"); } - else if(status == 499) + else if(status == HTTP_INTERNAL_ERROR) { error_text = getString("server_forbidden_text"); } diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h index 64f0b6b550..30327378ef 100644 --- a/indra/newview/llpanelplaceinfo.h +++ b/indra/newview/llpanelplaceinfo.h @@ -86,7 +86,7 @@ public: void displayParcelInfo(const LLUUID& region_id, const LLVector3d& pos_global); - /*virtual*/ void setErrorStatus(U32 status, const std::string& reason); + /*virtual*/ void setErrorStatus(S32 status, const std::string& reason); /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 6c2a01fc82..730df2ea23 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -217,7 +217,7 @@ public: LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id); } } - /*virtual*/ void setErrorStatus(U32 status, const std::string& reason) + /*virtual*/ void setErrorStatus(S32 status, const std::string& reason) { llerrs << "Can't complete remote parcel request. Http Status: " << status << ". Reason : " << reason << llendl; diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp index c277359133..a9c755de35 100644 --- a/indra/newview/llpathfindingmanager.cpp +++ b/indra/newview/llpathfindingmanager.cpp @@ -103,17 +103,16 @@ LLHTTPRegistration gHTTPRegistrationAgentStateChangeNode class NavMeshStatusResponder : public LLHTTPClient::Responder { + LOG_CLASS(NavMeshStatusResponder); public: - NavMeshStatusResponder(const std::string &pCapabilityURL, LLViewerRegion *pRegion, bool pIsGetStatusOnly); + NavMeshStatusResponder(LLViewerRegion *pRegion, bool pIsGetStatusOnly); virtual ~NavMeshStatusResponder(); - virtual void result(const LLSD &pContent); - virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); - protected: + virtual void httpSuccess(); + virtual void httpFailure(); private: - std::string mCapabilityURL; LLViewerRegion *mRegion; LLUUID mRegionUUID; bool mIsGetStatusOnly; @@ -125,17 +124,16 @@ private: class NavMeshResponder : public LLHTTPClient::Responder { + LOG_CLASS(NavMeshResponder); public: - NavMeshResponder(const std::string &pCapabilityURL, U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr); + NavMeshResponder(U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr); virtual ~NavMeshResponder(); - virtual void result(const LLSD &pContent); - virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); - protected: + virtual void httpSuccess(); + virtual void httpFailure(); private: - std::string mCapabilityURL; U32 mNavMeshVersion; LLPathfindingNavMeshPtr mNavMeshPtr; }; @@ -146,17 +144,14 @@ private: class AgentStateResponder : public LLHTTPClient::Responder { + LOG_CLASS(AgentStateResponder); public: - AgentStateResponder(const std::string &pCapabilityURL); + AgentStateResponder(); virtual ~AgentStateResponder(); - virtual void result(const LLSD &pContent); - virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); - protected: - -private: - std::string mCapabilityURL; + virtual void httpSuccess(); + virtual void httpFailure(); }; @@ -165,17 +160,16 @@ private: //--------------------------------------------------------------------------- class NavMeshRebakeResponder : public LLHTTPClient::Responder { + LOG_CLASS(NavMeshRebakeResponder); public: - NavMeshRebakeResponder(const std::string &pCapabilityURL, LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback); + NavMeshRebakeResponder(LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback); virtual ~NavMeshRebakeResponder(); - virtual void result(const LLSD &pContent); - virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); - protected: + virtual void httpSuccess(); + virtual void httpFailure(); private: - std::string mCapabilityURL; LLPathfindingManager::rebake_navmesh_callback_t mRebakeNavMeshCallback; }; @@ -190,11 +184,9 @@ public: virtual ~LinksetsResponder(); void handleObjectLinksetsResult(const LLSD &pContent); - void handleObjectLinksetsError(U32 pStatus, const std::string &pReason, - const LLSD& pContent, const std::string &pURL); + void handleObjectLinksetsError(); void handleTerrainLinksetsResult(const LLSD &pContent); - void handleTerrainLinksetsError(U32 pStatus, const std::string &pReason, - const LLSD& pContent, const std::string &pURL); + void handleTerrainLinksetsError(); protected: @@ -227,17 +219,16 @@ typedef boost::shared_ptr LinksetsResponderPtr; class ObjectLinksetsResponder : public LLHTTPClient::Responder { + LOG_CLASS(ObjectLinksetsResponder); public: - ObjectLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr); + ObjectLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr); virtual ~ObjectLinksetsResponder(); - virtual void result(const LLSD &pContent); - virtual void errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent); - protected: + virtual void httpSuccess(); + virtual void httpFailure(); private: - std::string mCapabilityURL; LinksetsResponderPtr mLinksetsResponsderPtr; }; @@ -247,17 +238,16 @@ private: class TerrainLinksetsResponder : public LLHTTPClient::Responder { + LOG_CLASS(TerrainLinksetsResponder); public: - TerrainLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr); + TerrainLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr); virtual ~TerrainLinksetsResponder(); - virtual void result(const LLSD &pContent); - virtual void errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent); - protected: + virtual void httpSuccess(); + virtual void httpFailure(); private: - std::string mCapabilityURL; LinksetsResponderPtr mLinksetsResponsderPtr; }; @@ -267,17 +257,16 @@ private: class CharactersResponder : public LLHTTPClient::Responder { + LOG_CLASS(TerrainLinksetsResponder); public: - CharactersResponder(const std::string &pCapabilityURL, LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback); + CharactersResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback); virtual ~CharactersResponder(); - virtual void result(const LLSD &pContent); - virtual void errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent); - protected: + virtual void httpSuccess(); + virtual void httpFailure(); private: - std::string mCapabilityURL; LLPathfindingManager::request_id_t mRequestId; LLPathfindingManager::object_request_callback_t mCharactersCallback; }; @@ -364,7 +353,7 @@ void LLPathfindingManager::requestGetNavMeshForRegion(LLViewerRegion *pRegion, b std::string navMeshStatusURL = getNavMeshStatusURLForRegion(pRegion); llassert(!navMeshStatusURL.empty()); navMeshPtr->handleNavMeshCheckVersion(); - LLHTTPClient::ResponderPtr navMeshStatusResponder = new NavMeshStatusResponder(navMeshStatusURL, pRegion, pIsGetStatusOnly); + LLHTTPClient::ResponderPtr navMeshStatusResponder = new NavMeshStatusResponder(pRegion, pIsGetStatusOnly); LLHTTPClient::get(navMeshStatusURL, navMeshStatusResponder); } } @@ -398,12 +387,12 @@ void LLPathfindingManager::requestGetLinksets(request_id_t pRequestId, object_re bool doRequestTerrain = isAllowViewTerrainProperties(); LinksetsResponderPtr linksetsResponderPtr(new LinksetsResponder(pRequestId, pLinksetsCallback, true, doRequestTerrain)); - LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(objectLinksetsURL, linksetsResponderPtr); + LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(linksetsResponderPtr); LLHTTPClient::get(objectLinksetsURL, objectLinksetsResponder); if (doRequestTerrain) { - LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(terrainLinksetsURL, linksetsResponderPtr); + LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(linksetsResponderPtr); LLHTTPClient::get(terrainLinksetsURL, terrainLinksetsResponder); } } @@ -447,13 +436,13 @@ void LLPathfindingManager::requestSetLinksets(request_id_t pRequestId, const LLP if (!objectPostData.isUndefined()) { - LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(objectLinksetsURL, linksetsResponderPtr); + LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(linksetsResponderPtr); LLHTTPClient::put(objectLinksetsURL, objectPostData, objectLinksetsResponder); } if (!terrainPostData.isUndefined()) { - LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(terrainLinksetsURL, linksetsResponderPtr); + LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(linksetsResponderPtr); LLHTTPClient::put(terrainLinksetsURL, terrainPostData, terrainLinksetsResponder); } } @@ -486,7 +475,7 @@ void LLPathfindingManager::requestGetCharacters(request_id_t pRequestId, object_ { pCharactersCallback(pRequestId, kRequestStarted, emptyCharacterListPtr); - LLHTTPClient::ResponderPtr charactersResponder = new CharactersResponder(charactersURL, pRequestId, pCharactersCallback); + LLHTTPClient::ResponderPtr charactersResponder = new CharactersResponder(pRequestId, pCharactersCallback); LLHTTPClient::get(charactersURL, charactersResponder); } } @@ -519,7 +508,7 @@ void LLPathfindingManager::requestGetAgentState() { std::string agentStateURL = getAgentStateURLForRegion(currentRegion); llassert(!agentStateURL.empty()); - LLHTTPClient::ResponderPtr responder = new AgentStateResponder(agentStateURL); + LLHTTPClient::ResponderPtr responder = new AgentStateResponder(); LLHTTPClient::get(agentStateURL, responder); } } @@ -543,7 +532,7 @@ void LLPathfindingManager::requestRebakeNavMesh(rebake_navmesh_callback_t pRebak llassert(!navMeshStatusURL.empty()); LLSD postData; postData["command"] = "rebuild"; - LLHTTPClient::ResponderPtr responder = new NavMeshRebakeResponder(navMeshStatusURL, pRebakeNavMeshCallback); + LLHTTPClient::ResponderPtr responder = new NavMeshRebakeResponder(pRebakeNavMeshCallback); LLHTTPClient::post(navMeshStatusURL, postData, responder); } } @@ -565,7 +554,7 @@ void LLPathfindingManager::sendRequestGetNavMeshForRegion(LLPathfindingNavMeshPt else { navMeshPtr->handleNavMeshStart(pNavMeshStatus); - LLHTTPClient::ResponderPtr responder = new NavMeshResponder(navMeshURL, pNavMeshStatus.getVersion(), navMeshPtr); + LLHTTPClient::ResponderPtr responder = new NavMeshResponder(pNavMeshStatus.getVersion(), navMeshPtr); LLSD postData; LLHTTPClient::post(navMeshURL, postData, responder); @@ -779,9 +768,8 @@ void LLAgentStateChangeNode::post(ResponsePtr pResponse, const LLSD &pContext, c // NavMeshStatusResponder //--------------------------------------------------------------------------- -NavMeshStatusResponder::NavMeshStatusResponder(const std::string &pCapabilityURL, LLViewerRegion *pRegion, bool pIsGetStatusOnly) +NavMeshStatusResponder::NavMeshStatusResponder(LLViewerRegion *pRegion, bool pIsGetStatusOnly) : LLHTTPClient::Responder(), - mCapabilityURL(pCapabilityURL), mRegion(pRegion), mRegionUUID(), mIsGetStatusOnly(pIsGetStatusOnly) @@ -796,15 +784,15 @@ NavMeshStatusResponder::~NavMeshStatusResponder() { } -void NavMeshStatusResponder::result(const LLSD &pContent) +void NavMeshStatusResponder::httpSuccess() { - LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID, pContent); + LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID, getContent()); LLPathfindingManager::getInstance()->handleNavMeshStatusRequest(navMeshStatus, mRegion, mIsGetStatusOnly); } -void NavMeshStatusResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent) +void NavMeshStatusResponder::httpFailure() { - llwarns << "NavMeshStatusResponder error [status:" << pStatus << "]: " << pContent << llendl; + llwarns << dumpResponse() << llendl; LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID); LLPathfindingManager::getInstance()->handleNavMeshStatusRequest(navMeshStatus, mRegion, mIsGetStatusOnly); } @@ -813,9 +801,8 @@ void NavMeshStatusResponder::errorWithContent(U32 pStatus, const std::string& pR // NavMeshResponder //--------------------------------------------------------------------------- -NavMeshResponder::NavMeshResponder(const std::string &pCapabilityURL, U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr) +NavMeshResponder::NavMeshResponder(U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr) : LLHTTPClient::Responder(), - mCapabilityURL(pCapabilityURL), mNavMeshVersion(pNavMeshVersion), mNavMeshPtr(pNavMeshPtr) { @@ -825,23 +812,23 @@ NavMeshResponder::~NavMeshResponder() { } -void NavMeshResponder::result(const LLSD &pContent) +void NavMeshResponder::httpSuccess() { - mNavMeshPtr->handleNavMeshResult(pContent, mNavMeshVersion); + mNavMeshPtr->handleNavMeshResult(getContent(), mNavMeshVersion); } -void NavMeshResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent) +void NavMeshResponder::httpFailure() { - mNavMeshPtr->handleNavMeshError(pStatus, pReason, pContent, mCapabilityURL, mNavMeshVersion); + llwarns << dumpResponse() << llendl; + mNavMeshPtr->handleNavMeshError(mNavMeshVersion); } //--------------------------------------------------------------------------- // AgentStateResponder //--------------------------------------------------------------------------- -AgentStateResponder::AgentStateResponder(const std::string &pCapabilityURL) +AgentStateResponder::AgentStateResponder() : LLHTTPClient::Responder() -, mCapabilityURL(pCapabilityURL) { } @@ -849,17 +836,18 @@ AgentStateResponder::~AgentStateResponder() { } -void AgentStateResponder::result(const LLSD &pContent) +void AgentStateResponder::httpSuccess() { + const LLSD& pContent = getContent(); llassert(pContent.has(AGENT_STATE_CAN_REBAKE_REGION_FIELD)); llassert(pContent.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).isBoolean()); BOOL canRebakeRegion = pContent.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).asBoolean(); LLPathfindingManager::getInstance()->handleAgentState(canRebakeRegion); } -void AgentStateResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent) +void AgentStateResponder::httpFailure() { - llwarns << "AgentStateResponder error [status:" << pStatus << "]: " << pContent << llendl; + llwarns << dumpResponse() << llendl; LLPathfindingManager::getInstance()->handleAgentState(FALSE); } @@ -867,9 +855,8 @@ void AgentStateResponder::errorWithContent(U32 pStatus, const std::string &pReas //--------------------------------------------------------------------------- // navmesh rebake responder //--------------------------------------------------------------------------- -NavMeshRebakeResponder::NavMeshRebakeResponder(const std::string &pCapabilityURL, LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback) +NavMeshRebakeResponder::NavMeshRebakeResponder(LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback) : LLHTTPClient::Responder(), - mCapabilityURL(pCapabilityURL), mRebakeNavMeshCallback(pRebakeNavMeshCallback) { } @@ -878,14 +865,14 @@ NavMeshRebakeResponder::~NavMeshRebakeResponder() { } -void NavMeshRebakeResponder::result(const LLSD &pContent) +void NavMeshRebakeResponder::httpSuccess() { mRebakeNavMeshCallback(true); } -void NavMeshRebakeResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent) +void NavMeshRebakeResponder::httpFailure() { - llwarns << "NavMeshRebakeResponder error [status:" << pStatus << "]: " << pContent << llendl; + llwarns << dumpResponse() << llendl; mRebakeNavMeshCallback(false); } @@ -918,11 +905,8 @@ void LinksetsResponder::handleObjectLinksetsResult(const LLSD &pContent) } } -void LinksetsResponder::handleObjectLinksetsError(U32 pStatus, const std::string &pReason, - const LLSD& pContent, const std::string &pURL) +void LinksetsResponder::handleObjectLinksetsError() { - llwarns << "LinksetsResponder object linksets error with request to URL '" << pURL << "' [status:" - << pStatus << "]: " << pContent << llendl; mObjectMessagingState = kReceivedError; if (mTerrainMessagingState != kWaiting) { @@ -941,11 +925,8 @@ void LinksetsResponder::handleTerrainLinksetsResult(const LLSD &pContent) } } -void LinksetsResponder::handleTerrainLinksetsError(U32 pStatus, const std::string &pReason, - const LLSD& pContent, const std::string &pURL) +void LinksetsResponder::handleTerrainLinksetsError() { - llwarns << "LinksetsResponder terrain linksets error with request to URL '" << pURL << "' [status:" - << pStatus << "]: " << pContent << llendl; mTerrainMessagingState = kReceivedError; if (mObjectMessagingState != kWaiting) { @@ -979,9 +960,8 @@ void LinksetsResponder::sendCallback() // ObjectLinksetsResponder //--------------------------------------------------------------------------- -ObjectLinksetsResponder::ObjectLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr) +ObjectLinksetsResponder::ObjectLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr) : LLHTTPClient::Responder(), - mCapabilityURL(pCapabilityURL), mLinksetsResponsderPtr(pLinksetsResponsderPtr) { } @@ -990,23 +970,23 @@ ObjectLinksetsResponder::~ObjectLinksetsResponder() { } -void ObjectLinksetsResponder::result(const LLSD &pContent) +void ObjectLinksetsResponder::httpSuccess() { - mLinksetsResponsderPtr->handleObjectLinksetsResult(pContent); + mLinksetsResponsderPtr->handleObjectLinksetsResult(getContent()); } -void ObjectLinksetsResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent) +void ObjectLinksetsResponder::httpFailure() { - mLinksetsResponsderPtr->handleObjectLinksetsError(pStatus, pReason, pContent, mCapabilityURL); + llwarns << dumpResponse() << llendl; + mLinksetsResponsderPtr->handleObjectLinksetsError(); } //--------------------------------------------------------------------------- // TerrainLinksetsResponder //--------------------------------------------------------------------------- -TerrainLinksetsResponder::TerrainLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr) +TerrainLinksetsResponder::TerrainLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr) : LLHTTPClient::Responder(), - mCapabilityURL(pCapabilityURL), mLinksetsResponsderPtr(pLinksetsResponsderPtr) { } @@ -1015,23 +995,23 @@ TerrainLinksetsResponder::~TerrainLinksetsResponder() { } -void TerrainLinksetsResponder::result(const LLSD &pContent) +void TerrainLinksetsResponder::httpSuccess() { - mLinksetsResponsderPtr->handleTerrainLinksetsResult(pContent); + mLinksetsResponsderPtr->handleTerrainLinksetsResult(getContent()); } -void TerrainLinksetsResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent) +void TerrainLinksetsResponder::httpFailure() { - mLinksetsResponsderPtr->handleTerrainLinksetsError(pStatus, pReason, pContent, mCapabilityURL); + llwarns << dumpResponse() << llendl; + mLinksetsResponsderPtr->handleTerrainLinksetsError(); } //--------------------------------------------------------------------------- // CharactersResponder //--------------------------------------------------------------------------- -CharactersResponder::CharactersResponder(const std::string &pCapabilityURL, LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback) +CharactersResponder::CharactersResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback) : LLHTTPClient::Responder(), - mCapabilityURL(pCapabilityURL), mRequestId(pRequestId), mCharactersCallback(pCharactersCallback) { @@ -1041,15 +1021,15 @@ CharactersResponder::~CharactersResponder() { } -void CharactersResponder::result(const LLSD &pContent) +void CharactersResponder::httpSuccess() { - LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList(pContent)); + LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList(getContent())); mCharactersCallback(mRequestId, LLPathfindingManager::kRequestCompleted, characterListPtr); } -void CharactersResponder::errorWithContent(U32 pStatus, const std::string &pReason, const LLSD& pContent) +void CharactersResponder::httpFailure() { - llwarns << "CharactersResponder error [status:" << pStatus << "]: " << pContent << llendl; + llwarns << dumpResponse() << llendl; LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList()); mCharactersCallback(mRequestId, LLPathfindingManager::kRequestError, characterListPtr); diff --git a/indra/newview/llpathfindingnavmesh.cpp b/indra/newview/llpathfindingnavmesh.cpp index 0c23e5ac92..555105cf40 100644 --- a/indra/newview/llpathfindingnavmesh.cpp +++ b/indra/newview/llpathfindingnavmesh.cpp @@ -184,10 +184,8 @@ void LLPathfindingNavMesh::handleNavMeshError() setRequestStatus(kNavMeshRequestError); } -void LLPathfindingNavMesh::handleNavMeshError(U32 pStatus, const std::string &pReason, const LLSD& pContent, const std::string &pURL, U32 pNavMeshVersion) +void LLPathfindingNavMesh::handleNavMeshError(U32 pNavMeshVersion) { - llwarns << "LLPathfindingNavMesh error with request to URL '" << pURL << "' [status:" - << pStatus << "]: " << pContent << llendl; if (mNavMeshStatus.getVersion() == pNavMeshVersion) { handleNavMeshError(); diff --git a/indra/newview/llpathfindingnavmesh.h b/indra/newview/llpathfindingnavmesh.h index b872ccad7c..87f32b8d56 100644 --- a/indra/newview/llpathfindingnavmesh.h +++ b/indra/newview/llpathfindingnavmesh.h @@ -74,7 +74,7 @@ public: void handleNavMeshResult(const LLSD &pContent, U32 pNavMeshVersion); void handleNavMeshNotEnabled(); void handleNavMeshError(); - void handleNavMeshError(U32 pStatus, const std::string &pReason, const LLSD& pContent, const std::string &pURL, U32 pNavMeshVersion); + void handleNavMeshError(U32 pNavMeshVersion); protected: diff --git a/indra/newview/llproductinforequest.cpp b/indra/newview/llproductinforequest.cpp index 1390000fc5..94a6389f8a 100644 --- a/indra/newview/llproductinforequest.cpp +++ b/indra/newview/llproductinforequest.cpp @@ -35,18 +35,24 @@ class LLProductInfoRequestResponder : public LLHTTPClient::Responder { -public: + LOG_CLASS(LLProductInfoRequestResponder); +private: //If we get back a normal response, handle it here - virtual void result(const LLSD& content) + /* virtual */ void httpSuccess() { - LLProductInfoRequestManager::instance().setSkuDescriptions(content); + const LLSD& content = getContent(); + if (!content.isArray()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + LLProductInfoRequestManager::instance().setSkuDescriptions(getContent()); } //If we get back an error (not found, etc...), handle it here - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + /* virtual */ void httpFailure() { - llwarns << "LLProductInfoRequest error [status:" - << status << ":] " << content << llendl; + llwarns << dumpResponse() << llendl; } }; diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp index 500dec7ee5..7418bbf615 100644 --- a/indra/newview/llremoteparcelrequest.cpp +++ b/indra/newview/llremoteparcelrequest.cpp @@ -47,9 +47,15 @@ LLRemoteParcelRequestResponder::LLRemoteParcelRequestResponder(LLHandlesetErrorStatus(status, reason); + observer->setErrorStatus(getStatus(), getReason()); } } diff --git a/indra/newview/llremoteparcelrequest.h b/indra/newview/llremoteparcelrequest.h index b87056573b..0f8ae41d76 100644 --- a/indra/newview/llremoteparcelrequest.h +++ b/indra/newview/llremoteparcelrequest.h @@ -37,16 +37,17 @@ class LLRemoteParcelInfoObserver; class LLRemoteParcelRequestResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLRemoteParcelRequestResponder); public: LLRemoteParcelRequestResponder(LLHandle observer_handle); +private: //If we get back a normal response, handle it here - /*virtual*/ void result(const LLSD& content); + /*virtual*/ void httpSuccess(); //If we get back an error (not found, etc...), handle it here - /*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content); + /*virtual*/ void httpFailure(); -protected: LLHandle mObserverHandle; }; @@ -78,7 +79,7 @@ public: virtual ~LLRemoteParcelInfoObserver() {} virtual void processParcelInfo(const LLParcelData& parcel_data) = 0; virtual void setParcelID(const LLUUID& parcel_id) = 0; - virtual void setErrorStatus(U32 status, const std::string& reason) = 0; + virtual void setErrorStatus(S32 status, const std::string& reason) = 0; LLHandle getObserverHandle() const { return mObserverHandle; } protected: diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 890bc0f42d..1065b744b9 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -720,21 +720,23 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update) class ModerationResponder : public LLHTTPClient::Responder { + LOG_CLASS(ModerationResponder); public: ModerationResponder(const LLUUID& session_id) { mSessionID = session_id; } - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) +protected: + virtual void httpFailure() { - llwarns << "ModerationResponder error [status:" << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; if ( gIMMgr ) { //403 == you're not a mod //should be disabled if you're not a moderator - if ( 403 == status ) + if ( HTTP_FORBIDDEN == getStatus() ) { gIMMgr->showSessionEventError( "mute", diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 81bc70906d..d61a87c031 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -36,7 +36,7 @@ #include "lldir.h" #include "llhttpclient.h" -#include "llhttpstatuscodes.h" +#include "llhttpconstants.h" #include "llimage.h" #include "llimagej2c.h" #include "llimageworker.h" @@ -2350,9 +2350,10 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mHttpRequest = new LLCore::HttpRequest; mHttpOptions = new LLCore::HttpOptions; mHttpHeaders = new LLCore::HttpHeaders; - mHttpHeaders->mHeaders.push_back("Accept: image/x-j2c"); + // *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ? + mHttpHeaders->mHeaders.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C); mHttpMetricsHeaders = new LLCore::HttpHeaders; - mHttpMetricsHeaders->mHeaders.push_back("Content-Type: application/llsd+xml"); + mHttpMetricsHeaders->mHeaders.push_back(HTTP_HEADER_CONTENT_TYPE + ": " + HTTP_CONTENT_LLSD_XML); mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicyDefault(); } @@ -3950,7 +3951,8 @@ void LLTextureFetchDebugger::init() if (! mHttpHeaders) { mHttpHeaders = new LLCore::HttpHeaders; - mHttpHeaders->mHeaders.push_back("Accept: image/x-j2c"); + // *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ? + mHttpHeaders->mHeaders.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C); } } diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index f3d8de1904..b9840fa3e4 100755 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -84,7 +84,7 @@ bool LLGoogleTranslationHandler::parseResponse( return false; } - if (status != STATUS_OK) + if (status != HTTP_OK) { // Request failed. Extract error message from the response. parseErrorResponse(root, status, err_msg); @@ -186,7 +186,7 @@ bool LLBingTranslationHandler::parseResponse( std::string& detected_lang, std::string& err_msg) const { - if (status != STATUS_OK) + if (status != HTTP_OK) { static const std::string MSG_BEGIN_MARKER = "Message: "; size_t begin = body.find(MSG_BEGIN_MARKER); @@ -251,8 +251,6 @@ LLTranslate::TranslationReceiver::TranslationReceiver(const std::string& from_la // virtual void LLTranslate::TranslationReceiver::completedRaw( - U32 http_status, - const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { @@ -262,8 +260,8 @@ void LLTranslate::TranslationReceiver::completedRaw( const std::string body = strstrm.str(); std::string translation, detected_lang, err_msg; - int status = http_status; - LL_DEBUGS("Translate") << "HTTP status: " << status << " " << reason << LL_ENDL; + int status = getStatus(); + LL_DEBUGS("Translate") << "HTTP status: " << status << " " << getReason() << LL_ENDL; LL_DEBUGS("Translate") << "Response body: " << body << LL_ENDL; if (mHandler.parseResponse(status, body, translation, detected_lang, err_msg)) { @@ -301,12 +299,10 @@ LLTranslate::EService LLTranslate::KeyVerificationReceiver::getService() const // virtual void LLTranslate::KeyVerificationReceiver::completedRaw( - U32 http_status, - const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { - bool ok = (http_status == 200); + bool ok = (getStatus() == HTTP_OK); setVerificationStatus(ok); } @@ -398,8 +394,8 @@ void LLTranslate::sendRequest(const std::string& url, LLHTTPClient::ResponderPtr LLVersionInfo::getPatch(), LLVersionInfo::getBuild()); - sHeader.insert("Accept", "text/plain"); - sHeader.insert("User-Agent", user_agent); + sHeader.insert(HTTP_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN); + sHeader.insert(HTTP_HEADER_USER_AGENT, user_agent); } LLHTTPClient::get(url, responder, sHeader, REQUEST_TIMEOUT); diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h index db5ad9479c..972274714a 100755 --- a/indra/newview/lltranslate.h +++ b/indra/newview/lltranslate.h @@ -95,9 +95,6 @@ public: virtual bool isConfigured() const = 0; virtual ~LLTranslationAPIHandler() {} - -protected: - static const int STATUS_OK = 200; }; /// Google Translate v2 API handler. @@ -201,8 +198,6 @@ public : * @see mHandler */ /*virtual*/ void completedRaw( - U32 http_status, - const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer); @@ -250,8 +245,6 @@ public : * @see setVerificationStatus() */ /*virtual*/ void completedRaw( - U32 http_status, - const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer); diff --git a/indra/newview/lluploadfloaterobservers.cpp b/indra/newview/lluploadfloaterobservers.cpp index 1d777b3f7f..88c48ba0a3 100644 --- a/indra/newview/lluploadfloaterobservers.cpp +++ b/indra/newview/lluploadfloaterobservers.cpp @@ -1,6 +1,6 @@ /** * @file lluploadfloaterobservers.cpp - * @brief LLUploadModelPremissionsResponder definition + * @brief LLUploadModelPermissionsResponder definition * * $LicenseInfo:firstyear=2011&license=viewerlgpl$ * Second Life Viewer Source Code @@ -28,26 +28,31 @@ #include "lluploadfloaterobservers.h" -LLUploadModelPremissionsResponder::LLUploadModelPremissionsResponder(const LLHandle& observer) +LLUploadModelPermissionsResponder::LLUploadModelPermissionsResponder(const LLHandle& observer) :mObserverHandle(observer) { } -void LLUploadModelPremissionsResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLUploadModelPermissionsResponder::httpFailure() { - llwarns << "LLUploadModelPremissionsResponder error [status:" - << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; LLUploadPermissionsObserver* observer = mObserverHandle.get(); if (observer) { - observer->setPermissonsErrorStatus(status, reason); + observer->setPermissonsErrorStatus(getStatus(), getReason()); } } -void LLUploadModelPremissionsResponder::result(const LLSD& content) +void LLUploadModelPermissionsResponder::httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } LLUploadPermissionsObserver* observer = mObserverHandle.get(); if (observer) @@ -55,3 +60,4 @@ void LLUploadModelPremissionsResponder::result(const LLSD& content) observer->onPermissionsReceived(content); } } + diff --git a/indra/newview/lluploadfloaterobservers.h b/indra/newview/lluploadfloaterobservers.h index b43ddb44d9..4ff4a827a5 100644 --- a/indra/newview/lluploadfloaterobservers.h +++ b/indra/newview/lluploadfloaterobservers.h @@ -1,6 +1,6 @@ /** * @file lluploadfloaterobservers.h - * @brief LLUploadModelPremissionsResponder declaration + * @brief LLUploadModelPermissionsResponder declaration * * $LicenseInfo:firstyear=2011&license=viewerlgpl$ * Second Life Viewer Source Code @@ -39,7 +39,7 @@ public: virtual ~LLUploadPermissionsObserver() {} virtual void onPermissionsReceived(const LLSD& result) = 0; - virtual void setPermissonsErrorStatus(U32 status, const std::string& reason) = 0; + virtual void setPermissonsErrorStatus(S32 status, const std::string& reason) = 0; LLHandle getPermObserverHandle() const {return mUploadPermObserverHandle;} @@ -54,7 +54,7 @@ public: virtual ~LLWholeModelFeeObserver() {} virtual void onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url) = 0; - virtual void setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) = 0; + virtual void setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason) = 0; LLHandle getWholeModelFeeObserverHandle() const { return mWholeModelFeeObserverHandle; } @@ -80,17 +80,16 @@ protected: }; -class LLUploadModelPremissionsResponder : public LLHTTPClient::Responder +class LLUploadModelPermissionsResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLUploadModelPermissionsResponder); public: - - LLUploadModelPremissionsResponder(const LLHandle& observer); - - void errorWithContent(U32 status, const std::string& reason, const LLSD& content); - - void result(const LLSD& content); + LLUploadModelPermissionsResponder(const LLHandle& observer); private: + /* virtual */ void httpSuccess(); + /* virtual */ void httpFailure(); + LLHandle mObserverHandle; }; diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp index 1ac6a90894..07fceefde0 100644 --- a/indra/newview/llviewerdisplayname.cpp +++ b/indra/newview/llviewerdisplayname.cpp @@ -57,12 +57,12 @@ namespace LLViewerDisplayName class LLSetDisplayNameResponder : public LLHTTPClient::Responder { -public: + LOG_CLASS(LLSetDisplayNameResponder); +private: // only care about errors - /*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + /*virtual*/ void httpFailure() { - llwarns << "LLSetDisplayNameResponder error [status:" - << status << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; LLViewerDisplayName::sSetDisplayNameSignal(false, "", LLSD()); LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots(); } @@ -85,7 +85,7 @@ void LLViewerDisplayName::set(const std::string& display_name, const set_name_sl // People API can return localized error messages. Indicate our // language preference via header. LLSD headers; - headers["Accept-Language"] = LLUI::getLanguage(); + headers[HTTP_HEADER_ACCEPT_LANGUAGE] = LLUI::getLanguage(); // People API requires both the old and new value to change a variable. // Our display name will be in cache before the viewer's UI is available @@ -127,7 +127,7 @@ public: LLSD body = input["body"]; S32 status = body["status"].asInteger(); - bool success = (status == 200); + bool success = (status == HTTP_OK); std::string reason = body["reason"].asString(); LLSD content = body["content"]; @@ -136,7 +136,7 @@ public: // If viewer's concept of display name is out-of-date, the set request // will fail with 409 Conflict. If that happens, fetch up-to-date // name information. - if (status == 409) + if (status == HTTP_CONFLICT) { LLUUID agent_id = gAgent.getID(); // Flush stale data diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 2df028de69..8c29a03176 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -158,7 +158,7 @@ LLViewerMediaObserver::~LLViewerMediaObserver() // on the Panel Land Media and to discover the MIME type class LLMimeDiscoveryResponder : public LLHTTPClient::Responder { -LOG_CLASS(LLMimeDiscoveryResponder); + LOG_CLASS(LLMimeDiscoveryResponder); public: LLMimeDiscoveryResponder( viewer_media_t media_impl) : mMediaImpl(media_impl), @@ -177,13 +177,20 @@ public: disconnectOwner(); } - virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content) +private: + /* virtual */ void httpCompleted() { - std::string media_type = content["content-type"].asString(); + if (!isGoodStatus()) + { + llwarns << dumpResponse() + << " [headers:" << getResponseHeaders() << "]" << llendl; + } + const bool check_lower = true; + const std::string& media_type = getResponseHeader(HTTP_HEADER_CONTENT_TYPE, check_lower); std::string::size_type idx1 = media_type.find_first_of(";"); std::string mime_type = media_type.substr(0, idx1); - lldebugs << "status is " << status << ", media type \"" << media_type << "\"" << llendl; + lldebugs << "status is " << getStatus() << ", media type \"" << media_type << "\"" << llendl; // 2xx status codes indicate success. // Most 4xx status codes are successful enough for our purposes. @@ -200,32 +207,27 @@ public: // ) // We now no longer check the error code returned from the probe. // If we have a mime type, use it. If not, default to the web plugin and let it handle error reporting. - if(1) + //if(1) { // The probe was successful. if(mime_type.empty()) { // Some sites don't return any content-type header at all. // Treat an empty mime type as text/html. - mime_type = "text/html"; + mime_type = HTTP_CONTENT_TEXT_HTML; } - - completeAny(status, mime_type); } - else - { - llwarns << "responder failed with status " << status << ", reason " << reason << llendl; - - if(mMediaImpl) - { - mMediaImpl->mMediaSourceFailed = true; - } - } - - } + //else + //{ + // llwarns << "responder failed with status " << dumpResponse() << llendl; + // + // if(mMediaImpl) + // { + // mMediaImpl->mMediaSourceFailed = true; + // } + // return; + //} - void completeAny(U32 status, const std::string& mime_type) - { // the call to initializeMedia may disconnect the responder, which will clear mMediaImpl. // Make a local copy so we can call loadURI() afterwards. LLViewerMediaImpl *impl = mMediaImpl; @@ -241,6 +243,7 @@ public: } } +public: void cancelRequest() { disconnectOwner(); @@ -269,7 +272,7 @@ public: class LLViewerMediaOpenIDResponder : public LLHTTPClient::Responder { -LOG_CLASS(LLViewerMediaOpenIDResponder); + LOG_CLASS(LLViewerMediaOpenIDResponder); public: LLViewerMediaOpenIDResponder( ) { @@ -279,23 +282,18 @@ public: { } - /* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content) - { - LL_DEBUGS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL; - LL_DEBUGS("MediaAuth") << content << LL_ENDL; - std::string cookie = content["set-cookie"].asString(); - - LLViewerMedia::openIDCookieResponse(cookie); - } - /* virtual */ void completedRaw( - U32 status, - const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { - // This is just here to disable the default behavior (attempting to parse the response as llsd). - // We don't care about the content of the response, only the set-cookie header. + // We don't care about the content of the response, only the Set-Cookie header. + LL_DEBUGS("MediaAuth") << dumpResponse() + << " [headers:" << getResponseHeaders() << "]" << LL_ENDL; + const bool check_lower = true; + const std::string& cookie = getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower); + + // *TODO: What about bad status codes? Does this destroy previous cookies? + LLViewerMedia::openIDCookieResponse(cookie); } }; @@ -313,17 +311,25 @@ public: { } - /* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content) + void completedRaw( + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) { - LL_WARNS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL; + // We don't care about the content of the response, only the set-cookie header. + LL_WARNS("MediaAuth") << dumpResponse() + << " [headers:" << getResponseHeaders() << "]" << LL_ENDL; - LLSD stripped_content = content; + LLSD stripped_content = getResponseHeaders(); + // *TODO: Check that this works. + stripped_content.erase(HTTP_HEADER_SET_COOKIE); stripped_content.erase("set-cookie"); LL_WARNS("MediaAuth") << stripped_content << LL_ENDL; - std::string cookie = content["set-cookie"].asString(); + const bool check_lower = true; + const std::string& cookie = getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower); LL_DEBUGS("MediaAuth") << "cookie = " << cookie << LL_ENDL; + // *TODO: What about bad status codes? Does this destroy previous cookies? LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, mHost); // Set cookie for snapshot publishing. @@ -331,16 +337,6 @@ public: LLWebProfile::setAuthCookie(auth_cookie); } - void completedRaw( - U32 status, - const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) - { - // This is just here to disable the default behavior (attempting to parse the response as llsd). - // We don't care about the content of the response, only the set-cookie header. - } - std::string mHost; }; @@ -1387,10 +1383,12 @@ void LLViewerMedia::removeCookie(const std::string &name, const std::string &dom LLSD LLViewerMedia::getHeaders() { LLSD headers = LLSD::emptyMap(); - headers["Accept"] = "*/*"; - headers["Content-Type"] = "application/xml"; - headers["Cookie"] = sOpenIDCookie; - headers["User-Agent"] = getCurrentUserAgent(); + headers[HTTP_HEADER_ACCEPT] = "*/*"; + // *TODO: Should this be 'application/llsd+xml' ? + // *TODO: Should this even be set at all? This header is only not overridden in 'GET' methods. + headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML; + headers[HTTP_HEADER_COOKIE] = sOpenIDCookie; + headers[HTTP_HEADER_USER_AGENT] = getCurrentUserAgent(); return headers; } @@ -1431,9 +1429,9 @@ void LLViewerMedia::setOpenIDCookie() // Do a web profile get so we can store the cookie LLSD headers = LLSD::emptyMap(); - headers["Accept"] = "*/*"; - headers["Cookie"] = sOpenIDCookie; - headers["User-Agent"] = getCurrentUserAgent(); + headers[HTTP_HEADER_ACCEPT] = "*/*"; + headers[HTTP_HEADER_COOKIE] = sOpenIDCookie; + headers[HTTP_HEADER_USER_AGENT] = getCurrentUserAgent(); std::string profile_url = getProfileURL(""); LLURL raw_profile_url( profile_url.c_str() ); @@ -1463,9 +1461,9 @@ void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string LLSD headers = LLSD::emptyMap(); // Keep LLHTTPClient from adding an "Accept: application/llsd+xml" header - headers["Accept"] = "*/*"; + headers[HTTP_HEADER_ACCEPT] = "*/*"; // and use the expected content-type for a post, instead of the LLHTTPClient::postRaw() default of "application/octet-stream" - headers["Content-Type"] = "application/x-www-form-urlencoded"; + headers[HTTP_HEADER_CONTENT_TYPE] = "application/x-www-form-urlencoded"; // postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here. size_t size = openid_token.size(); @@ -1537,7 +1535,7 @@ void LLViewerMedia::createSpareBrowserMediaSource() // The null owner will keep the browser plugin from fully initializing // (specifically, it keeps LLPluginClassMedia from negotiating a size change, // which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color) - sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", NULL, 0, 0); + sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType(HTTP_CONTENT_TEXT_HTML, NULL, 0, 0); } } @@ -2633,16 +2631,16 @@ void LLViewerMediaImpl::navigateInternal() // Accept: application/llsd+xml // which is really not what we want. LLSD headers = LLSD::emptyMap(); - headers["Accept"] = "*/*"; + headers[HTTP_HEADER_ACCEPT] = "*/*"; // Allow cookies in the response, to prevent a redirect loop when accessing join.secondlife.com - headers["Cookie"] = ""; + headers[HTTP_HEADER_COOKIE] = ""; LLHTTPClient::getHeaderOnly( mMediaURL, new LLMimeDiscoveryResponder(this), headers, 10.0f); } else if("data" == scheme || "file" == scheme || "about" == scheme) { // FIXME: figure out how to really discover the type for these schemes // We use "data" internally for a text/html url for loading the login screen - if(initializeMedia("text/html")) + if(initializeMedia(HTTP_CONTENT_TEXT_HTML)) { loadURI(); } diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 0561e731e7..576b801d5b 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -671,6 +671,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) class LLObjectCostResponder : public LLCurl::Responder { + LOG_CLASS(LLObjectCostResponder); public: LLObjectCostResponder(const LLSD& object_ids) : mObjectIDs(object_ids) @@ -691,20 +692,19 @@ public: } } - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) +private: + /* virtual */ void httpFailure() { - llwarns - << "Transport error requesting object cost " - << "[status: " << statusNum << "]: " - << content << llendl; + llwarns << dumpResponse() << llendl; // TODO*: Error message to user // For now just clear the request from the pending list clear_object_list_pending_requests(); } - void result(const LLSD& content) + /* virtual */ void httpSuccess() { + const LLSD& content = getContent(); if ( !content.isMap() || content.has("error") ) { // Improper response or the request had an error, @@ -760,6 +760,7 @@ private: class LLPhysicsFlagsResponder : public LLCurl::Responder { + LOG_CLASS(LLPhysicsFlagsResponder); public: LLPhysicsFlagsResponder(const LLSD& object_ids) : mObjectIDs(object_ids) @@ -780,20 +781,19 @@ public: } } - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) +private: + /* virtual */ void httpFailure() { - llwarns - << "Transport error requesting object physics flags " - << "[status: " << statusNum << "]: " - << content << llendl; + llwarns << dumpResponse() << llendl; // TODO*: Error message to user // For now just clear the request from the pending list clear_object_list_pending_requests(); } - void result(const LLSD& content) + /* virtual void */ void httpSuccess() { + const LLSD& content = getContent(); if ( !content.isMap() || content.has("error") ) { // Improper response or the request had an error, diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index 386b2fd400..d7e14ac6f5 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -99,7 +99,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel) std::string mediaCurrentUrl = std::string( parcel->getMediaCurrentURL()); // if we have a current (link sharing) url, use it instead - if (mediaCurrentUrl != "" && parcel->getMediaType() == "text/html") + if (mediaCurrentUrl != "" && parcel->getMediaType() == HTTP_CONTENT_TEXT_HTML) { mediaUrl = mediaCurrentUrl; } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index b8b53aa6e4..2286bb09e1 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -204,24 +204,30 @@ class BaseCapabilitiesComplete : public LLHTTPClient::Responder { LOG_CLASS(BaseCapabilitiesComplete); public: - BaseCapabilitiesComplete(U64 region_handle, S32 id) + BaseCapabilitiesComplete(U64 region_handle, S32 id) : mRegionHandle(region_handle), mID(id) - { } + { } virtual ~BaseCapabilitiesComplete() { } - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) - { - LL_WARNS2("AppInit", "Capabilities") << "[status:" << statusNum << ":] " << content << LL_ENDL; + static BaseCapabilitiesComplete* build( U64 region_handle, S32 id ) + { + return new BaseCapabilitiesComplete(region_handle, id); + } + +private: + /* virtual */void httpFailure() + { + LL_WARNS2("AppInit", "Capabilities") << dumpResponse() << LL_ENDL; LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); if (regionp) { regionp->failedSeedCapability(); } - } + } - void result(const LLSD& content) - { + /* virtual */ void httpSuccess() + { LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); if(!regionp) //region was removed { @@ -234,11 +240,17 @@ public: return ; } + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } LLSD::map_const_iterator iter; for(iter = content.beginMap(); iter != content.endMap(); ++iter) { regionp->setCapability(iter->first, iter->second); - + LL_DEBUGS2("AppInit", "Capabilities") << "got capability for " << iter->first << LL_ENDL; @@ -257,11 +269,6 @@ public: } } - static BaseCapabilitiesComplete* build( U64 region_handle, S32 id ) - { - return new BaseCapabilitiesComplete(region_handle, id); - } - private: U64 mRegionHandle; S32 mID; @@ -278,19 +285,32 @@ public: virtual ~BaseCapabilitiesCompleteTracker() { } - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) + static BaseCapabilitiesCompleteTracker* build( U64 region_handle ) + { + return new BaseCapabilitiesCompleteTracker( region_handle ); + } + +private: + /* virtual */ void httpFailure() { - llwarns << "BaseCapabilitiesCompleteTracker error [status:" - << statusNum << "]: " << content << llendl; + llwarns << dumpResponse() << llendl; } - void result(const LLSD& content) + /* virtual */ void httpSuccess() { LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); if( !regionp ) { + LL_WARNS2("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL; return ; - } + } + + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } LLSD::map_const_iterator iter; for(iter = content.beginMap(); iter != content.endMap(); ++iter) { @@ -300,7 +320,8 @@ public: if ( regionp->getRegionImpl()->mCapabilities.size() != regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() ) { - llinfos<<"BaseCapabilitiesCompleteTracker "<<"Sim sent duplicate seed caps that differs in size - most likely content."<getRegionImpl()->mCapabilities.begin(); while (iter!=regionp->getRegionImpl()->mCapabilities.end() ) @@ -311,16 +332,11 @@ public: */ regionp->getRegionImplNC()->mSecondCapabilitiesTracker.clear(); } - } - static BaseCapabilitiesCompleteTracker* build( U64 region_handle ) - { - return new BaseCapabilitiesCompleteTracker( region_handle ); - } private: - U64 mRegionHandle; + U64 mRegionHandle; }; @@ -1728,31 +1744,37 @@ class SimulatorFeaturesReceived : public LLHTTPClient::Responder { LOG_CLASS(SimulatorFeaturesReceived); public: - SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle, + SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle, S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS) - : mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts) - { } - - - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) - { - LL_WARNS2("AppInit", "SimulatorFeatures") << "[status:" << statusNum << "]: " << content << LL_ENDL; + : mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts) + { } + +private: + /* virtual */ void httpFailure() + { + LL_WARNS2("AppInit", "SimulatorFeatures") << dumpResponse() << LL_ENDL; retry(); - } + } - void result(const LLSD& content) - { + /* virtual */ void httpSuccess() + { LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); if(!regionp) //region is removed or responder is not created. { - LL_WARNS2("AppInit", "SimulatorFeatures") << "Received results for region that no longer exists!" << LL_ENDL; + LL_WARNS2("AppInit", "SimulatorFeatures") + << "Received results for region that no longer exists!" << LL_ENDL; return ; } - + + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } regionp->setSimulatorFeatures(content); } -private: void retry() { if (mAttempt < mMaxAttempts) @@ -1762,7 +1784,7 @@ private: LLHTTPClient::get(mRetryURL, new SimulatorFeaturesReceived(*this), LLSD(), CAP_REQUEST_TIMEOUT); } } - + std::string mRetryURL; U64 mRegionHandle; S32 mAttempt; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 4ed01f36ab..a9256ed5ea 100755 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -527,18 +527,19 @@ void update_statistics() class ViewerStatsResponder : public LLHTTPClient::Responder { + LOG_CLASS(ViewerStatsResponder); public: - ViewerStatsResponder() { } + ViewerStatsResponder() { } - void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) - { - llwarns << "ViewerStatsResponder error [status:" << statusNum << "]: " - << content << llendl; - } +private: + /* virtual */ void httpFailure() + { + llwarns << dumpResponse() << llendl; + } - void result(const LLSD& content) - { - llinfos << "ViewerStatsResponder::result" << llendl; + /* virtual */ void httpSuccess() + { + llinfos << "OK" << llendl; } }; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index a98e9ce511..7e95263f4b 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1914,7 +1914,7 @@ void LLViewerWindow::initWorldUI() destinations->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); std::string url = gSavedSettings.getString("DestinationGuideURL"); url = LLWeb::expandURLSubstitutions(url, LLSD()); - destinations->navigateTo(url, "text/html"); + destinations->navigateTo(url, HTTP_CONTENT_TEXT_HTML); } LLMediaCtrl* avatar_picker = LLFloaterReg::getInstance("avatar")->findChild("avatar_picker_contents"); if (avatar_picker) @@ -1922,7 +1922,7 @@ void LLViewerWindow::initWorldUI() avatar_picker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); std::string url = gSavedSettings.getString("AvatarPickerURL"); url = LLWeb::expandURLSubstitutions(url, LLSD()); - avatar_picker->navigateTo(url, "text/html"); + avatar_picker->navigateTo(url, HTTP_CONTENT_TEXT_HTML); } } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 9be1de4f0e..81454f5da4 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2241,6 +2241,7 @@ LLSD LLVOAvatarSelf::metricsData() class ViewerAppearanceChangeMetricsResponder: public LLCurl::Responder { + LOG_CLASS(ViewerAppearanceChangeMetricsResponder); public: ViewerAppearanceChangeMetricsResponder( S32 expected_sequence, volatile const S32 & live_sequence, @@ -2251,32 +2252,25 @@ public: { } - virtual void completed(U32 status, - const std::string& reason, - const LLSD& content) +private: + /* virtual */ void httpSuccess() { - gPendingMetricsUploads--; // if we add retry, this should be moved to the isGoodStatus case. - if (isGoodStatus(status)) - { - LL_DEBUGS("Avatar") << "OK" << LL_ENDL; - result(content); - } - else - { - LL_WARNS("Avatar") << "Failed " << status << " reason " << reason << LL_ENDL; - errorWithContent(status,reason,content); - } - } + LL_DEBUGS("Avatar") << "OK" << LL_ENDL; - // virtual - void result(const LLSD & content) - { + gPendingMetricsUploads--; if (mLiveSequence == mExpectedSequence) { mReportingStarted = true; } } + /* virtual */ void httpFailure() + { + // if we add retry, this should be removed from the httpFailure case + LL_WARNS("Avatar") << dumpResponse() << LL_ENDL; + gPendingMetricsUploads--; + } + private: S32 mExpectedSequence; volatile const S32 & mLiveSequence; @@ -2425,6 +2419,7 @@ void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics() class CheckAgentAppearanceServiceResponder: public LLHTTPClient::Responder { + LOG_CLASS(CheckAgentAppearanceServiceResponder); public: CheckAgentAppearanceServiceResponder() { @@ -2434,22 +2429,24 @@ public: { } - /* virtual */ void result(const LLSD& content) +private: + /* virtual */ void httpSuccess() { - LL_DEBUGS("Avatar") << "status OK" << llendl; + LL_DEBUGS("Avatar") << "OK" << llendl; } // Error - /*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + /*virtual*/ void httpFailure() { if (isAgentAvatarValid()) { - LL_DEBUGS("Avatar") << "failed, will rebake [status:" - << status << "]: " << content << llendl; + LL_DEBUGS("Avatar") << "failed, will rebake " + << dumpResponse() << LL_ENDL; forceAppearanceUpdate(); } - } + } +public: static void forceAppearanceUpdate() { // Trying to rebake immediately after crossing region boundary diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 181735ee30..be836d7752 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -53,26 +53,27 @@ const U32 DEFAULT_RETRIES_COUNT = 3; class LLVoiceCallCapResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLVoiceCallCapResponder); public: LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {}; +protected: // called with bad status codes - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); - virtual void result(const LLSD& content); + virtual void httpFailure(); + virtual void httpSuccess(); private: LLUUID mSessionID; }; -void LLVoiceCallCapResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLVoiceCallCapResponder::httpFailure() { - LL_WARNS("Voice") << "LLVoiceCallCapResponder error [status:" - << status << "]: " << content << LL_ENDL; + LL_WARNS("Voice") << dumpResponse() << LL_ENDL; LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID); if ( channelp ) { - if ( 403 == status ) + if ( HTTP_FORBIDDEN == getStatus() ) { //403 == no ability LLNotificationsUtil::add( @@ -89,12 +90,18 @@ void LLVoiceCallCapResponder::errorWithContent(U32 status, const std::string& re } } -void LLVoiceCallCapResponder::result(const LLSD& content) +void LLVoiceCallCapResponder::httpSuccess() { LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID); if (channelp) { //*TODO: DEBUG SPAM + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } LLSD::map_const_iterator iter; for(iter = content.beginMap(); iter != content.endMap(); ++iter) { diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index e112c589e9..360f8f15a3 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -120,17 +120,19 @@ static int scale_speaker_volume(float volume) class LLVivoxVoiceAccountProvisionResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLVivoxVoiceAccountProvisionResponder); public: LLVivoxVoiceAccountProvisionResponder(int retries) { mRetries = retries; } - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) +private: + /* virtual */ void httpFailure() { LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, " << ( (mRetries > 0) ? "retrying" : "too many retries (giving up)" ) - << status << "]: " << content << LL_ENDL; + << " " << dumpResponse() << LL_ENDL; if ( mRetries > 0 ) { @@ -142,14 +144,19 @@ public: } } - virtual void result(const LLSD& content) + /* virtual */ void httpSuccess() { - std::string voice_sip_uri_hostname; std::string voice_account_server_uri; - LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << ll_pretty_print_sd(content) << LL_ENDL; + LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << dumpResponse() << LL_ENDL; + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } if(content.has("voice_sip_uri_hostname")) voice_sip_uri_hostname = content["voice_sip_uri_hostname"].asString(); @@ -162,7 +169,6 @@ public: content["password"].asString(), voice_sip_uri_hostname, voice_account_server_uri); - } private: @@ -193,33 +199,34 @@ static LLVivoxVoiceClientFriendsObserver *friendslist_listener = NULL; class LLVivoxVoiceClientCapResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLVivoxVoiceClientCapResponder); public: LLVivoxVoiceClientCapResponder(LLVivoxVoiceClient::state requesting_state) : mRequestingState(requesting_state) {}; +private: // called with bad status codes - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); - virtual void result(const LLSD& content); + /* virtual */ void httpFailure(); + /* virtual */ void httpSuccess(); -private: LLVivoxVoiceClient::state mRequestingState; // state }; -void LLVivoxVoiceClientCapResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLVivoxVoiceClientCapResponder::httpFailure() { - LL_WARNS("Voice") << "LLVivoxVoiceClientCapResponder error [status:" - << status << "]: " << content << LL_ENDL; + LL_WARNS("Voice") << dumpResponse() << LL_ENDL; LLVivoxVoiceClient::getInstance()->sessionTerminate(); } -void LLVivoxVoiceClientCapResponder::result(const LLSD& content) +void LLVivoxVoiceClientCapResponder::httpSuccess() { LLSD::map_const_iterator iter; - LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << ll_pretty_print_sd(content) << LL_ENDL; + LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << dumpResponse() << LL_ENDL; std::string uri; std::string credentials; + const LLSD& content = getContent(); if ( content.has("voice_credentials") ) { LLSD voice_credentials = content["voice_credentials"]; @@ -2982,7 +2989,7 @@ void LLVivoxVoiceClient::loginResponse(int statusCode, std::string &statusString // Status code of 20200 means "bad password". We may want to special-case that at some point. - if ( statusCode == 401 ) + if ( statusCode == HTTP_UNAUTHORIZED ) { // Login failure which is probably caused by the delay after a user's password being updated. LL_INFOS("Voice") << "Account.Login response failure (" << statusCode << "): " << statusString << LL_ENDL; @@ -3484,7 +3491,7 @@ void LLVivoxVoiceClient::mediaStreamUpdatedEvent( switch(statusCode) { case 0: - case 200: + case HTTP_OK: // generic success // Don't change the saved error code (it may have been set elsewhere) break; @@ -3835,7 +3842,7 @@ void LLVivoxVoiceClient::messageEvent( LL_DEBUGS("Voice") << "Message event, session " << sessionHandle << " from " << uriString << LL_ENDL; // LL_DEBUGS("Voice") << " header " << messageHeader << ", body: \n" << messageBody << LL_ENDL; - if(messageHeader.find("text/html") != std::string::npos) + if(messageHeader.find(HTTP_CONTENT_TEXT_HTML) != std::string::npos) { std::string message; @@ -6119,9 +6126,10 @@ void LLVivoxVoiceClient::notifyStatusObservers(LLVoiceClientStatusObserver::ESta { switch(mAudioSession->mErrorStatusCode) { - case 404: // NOT_FOUND + case HTTP_NOT_FOUND: // NOT_FOUND + // *TODO: Should this be 503? case 480: // TEMPORARILY_UNAVAILABLE - case 408: // REQUEST_TIMEOUT + case HTTP_REQUEST_TIME_OUT: // REQUEST_TIMEOUT // call failed because other user was not available // treat this as an error case status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE; diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp index 641f338f2c..ee78ba20cb 100644 --- a/indra/newview/llwebprofile.cpp +++ b/indra/newview/llwebprofile.cpp @@ -67,9 +67,8 @@ public: { } + // *TODO: Check for 'application/json' content type, and parse json at the base class. /*virtual*/ void completedRaw( - U32 status, - const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { @@ -78,9 +77,9 @@ public: strstrm << istr.rdbuf(); const std::string body = strstrm.str(); - if (status != 200) + if (getStatus() != HTTP_OK) { - llwarns << "Failed to get upload config (" << status << ")" << llendl; + llwarns << "Failed to get upload config " << dumpResponse() << llendl; LLWebProfile::reportImageUploadStatus(false); return; } @@ -128,14 +127,12 @@ class LLWebProfileResponders::PostImageRedirectResponder : public LLHTTPClient:: public: /*virtual*/ void completedRaw( - U32 status, - const std::string& reason, const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { - if (status != 200) + if (getStatus() != HTTP_OK) { - llwarns << "Failed to upload image: " << status << " " << reason << llendl; + llwarns << "Failed to upload image " << dumpResponse() << llendl; LLWebProfile::reportImageUploadStatus(false); return; } @@ -161,33 +158,37 @@ class LLWebProfileResponders::PostImageResponder : public LLHTTPClient::Responde LOG_CLASS(LLWebProfileResponders::PostImageResponder); public: - /*virtual*/ void completedHeader(U32 status, const std::string& reason, const LLSD& content) + /*virtual*/ void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) { // Viewer seems to fail to follow a 303 redirect on POST request // (URLRequest Error: 65, Send failed since rewinding of the data stream failed). // Handle it manually. - if (status == 303) + if (getStatus() == HTTP_SEE_OTHER) { LLSD headers = LLViewerMedia::getHeaders(); - headers["Cookie"] = LLWebProfile::getAuthCookie(); - const std::string& redir_url = content["location"]; - LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << llendl; - LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers); + headers[HTTP_HEADER_COOKIE] = LLWebProfile::getAuthCookie(); + const bool check_lower=true; + const std::string& redir_url = getResponseHeader(HTTP_HEADER_LOCATION, check_lower); + if (redir_url.empty()) + { + llwarns << "Received empty redirection URL " << dumpResponse() << llendl; + LL_DEBUGS("Snapshots") << "[headers:" << getResponseHeaders() << "]" << LL_ENDL; + LLWebProfile::reportImageUploadStatus(false); + } + else + { + LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << llendl; + LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers); + } } else { - llwarns << "Unexpected POST status: " << status << " " << reason << llendl; - LL_DEBUGS("Snapshots") << "headers: [" << content << "]" << llendl; + llwarns << "Unexpected POST response " << dumpResponse() << llendl; + LL_DEBUGS("Snapshots") << "[headers:" << getResponseHeaders() << "]" << LL_ENDL; LLWebProfile::reportImageUploadStatus(false); } } - - // Override just to suppress warnings. - /*virtual*/ void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) - { - } }; /////////////////////////////////////////////////////////////////////////////// @@ -206,7 +207,7 @@ void LLWebProfile::uploadImage(LLPointer image, const std::str LL_DEBUGS("Snapshots") << "Requesting " << config_url << llendl; LLSD headers = LLViewerMedia::getHeaders(); - headers["Cookie"] = getAuthCookie(); + headers[HTTP_HEADER_COOKIE] = getAuthCookie(); LLHTTPClient::get(config_url, new LLWebProfileResponders::ConfigResponder(image), headers); } @@ -230,8 +231,8 @@ void LLWebProfile::post(LLPointer image, const LLSD& config, c const std::string boundary = "----------------------------0123abcdefab"; LLSD headers = LLViewerMedia::getHeaders(); - headers["Cookie"] = getAuthCookie(); - headers["Content-Type"] = "multipart/form-data; boundary=" + boundary; + headers[HTTP_HEADER_COOKIE] = getAuthCookie(); + headers[HTTP_HEADER_CONTENT_TYPE] = "multipart/form-data; boundary=" + boundary; std::ostringstream body; diff --git a/indra/newview/llwebsharing.cpp b/indra/newview/llwebsharing.cpp index 3a80051b9b..ba536ac582 100644 --- a/indra/newview/llwebsharing.cpp +++ b/indra/newview/llwebsharing.cpp @@ -32,7 +32,7 @@ #include "llagentui.h" #include "llbufferstream.h" #include "llhttpclient.h" -#include "llhttpstatuscodes.h" +#include "llhttpconstants.h" #include "llsdserialize.h" #include "llsdutil.h" #include "llurl.h" @@ -45,36 +45,57 @@ /////////////////////////////////////////////////////////////////////////////// // -class LLWebSharingConfigResponder : public LLHTTPClient::Responder + +class LLWebSharingJSONResponder : public LLHTTPClient::Responder { - LOG_CLASS(LLWebSharingConfigResponder); + LOG_CLASS(LLWebSharingJSONResponder); public: /// Overrides the default LLSD parsing behaviour, to allow parsing a JSON response. - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, + virtual void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { - LLSD content; LLBufferStream istr(channels, buffer.get()); LLPointer parser = new LLSDNotationParser(); - if (parser->parse(istr, content, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE) - { - LL_WARNS("WebSharing") << "Failed to deserialize LLSD from JSON response. " << " [" << status << "]: " << reason << LL_ENDL; - } - else + if (parser->parse(istr, mContent, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE) { - completed(status, reason, content); + if (HTTP_CONTENT_JSON == getResponseHeader(HTTP_HEADER_CONTENT_TYPE)) + { + mStatus = HTTP_INTERNAL_ERROR; + mReason = "Failed to deserialize LLSD from JSON response."; + char body[1025]; + body[1024] = '\0'; + istr.seekg(0, std::ios::beg); + istr.get(body,1024); + if (strlen(body) > 0) + { + mContent["body"] = body; + } + } } + + httpCompleted(); } +}; + +class LLWebSharingConfigResponder : public LLWebSharingJSONResponder +{ + LOG_CLASS(LLWebSharingConfigResponder); +private: - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + virtual void httpFailure() { - LL_WARNS("WebSharing") << "Error [status:" << status << "]: " << content << LL_ENDL; + LL_WARNS("WebSharing") << dumpResponse() << LL_ENDL; } - virtual void result(const LLSD& content) + virtual void httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } LLWebSharing::instance().receiveConfig(content); } }; @@ -87,39 +108,35 @@ class LLWebSharingOpenIDAuthResponder : public LLHTTPClient::Responder { LOG_CLASS(LLWebSharingOpenIDAuthResponder); public: - /* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content) - { - completed(status, reason, content); - } - - /* virtual */ void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, + /* virtual */ void completedRaw(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { /// Left empty to override the default LLSD parsing behaviour. + httpCompleted(); } - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) +private: + virtual void httpFailure() { - if (HTTP_UNAUTHORIZED == status) + if (HTTP_UNAUTHORIZED == getStatus()) { LL_WARNS("WebSharing") << "AU account not authenticated." << LL_ENDL; // *TODO: No account found on AU, so start the account creation process here. } else { - LL_WARNS("WebSharing") << "Error [status:" << status << "]: " << content << LL_ENDL; + LL_WARNS("WebSharing") << dumpResponse() << LL_ENDL; LLWebSharing::instance().retryOpenIDAuth(); } - } - virtual void result(const LLSD& content) + virtual void httpSuccess() { - if (content.has("set-cookie")) + const bool check_lower=true; + if (hasResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower)) { // OpenID request succeeded and returned a session cookie. - LLWebSharing::instance().receiveSessionCookie(content["set-cookie"].asString()); + LLWebSharing::instance().receiveSessionCookie(getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower)); } } }; @@ -128,38 +145,19 @@ public: /////////////////////////////////////////////////////////////////////////////// // -class LLWebSharingSecurityTokenResponder : public LLHTTPClient::Responder +class LLWebSharingSecurityTokenResponder : public LLWebSharingJSONResponder { LOG_CLASS(LLWebSharingSecurityTokenResponder); -public: - /// Overrides the default LLSD parsing behaviour, to allow parsing a JSON response. - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) +private: + virtual void httpFailure() { - LLSD content; - LLBufferStream istr(channels, buffer.get()); - LLPointer parser = new LLSDNotationParser(); - - if (parser->parse(istr, content, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE) - { - LL_WARNS("WebSharing") << "Failed to deserialize LLSD from JSON response. " << " [" << status << "]: " << reason << LL_ENDL; - LLWebSharing::instance().retryOpenIDAuth(); - } - else - { - completed(status, reason, content); - } - } - - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) - { - LL_WARNS("WebSharing") << "Error [status:" << status << "]: " << content << LL_ENDL; + LL_WARNS("WebSharing") << dumpResponse() << LL_ENDL; LLWebSharing::instance().retryOpenIDAuth(); } - virtual void result(const LLSD& content) + virtual void httpSuccess() { + const LLSD& content = getContent(); if (content[0].has("st") && content[0].has("expires")) { const std::string& token = content[0]["st"].asString(); @@ -172,7 +170,8 @@ public: } else { - LL_WARNS("WebSharing") << "No security token received." << LL_ENDL; + failureResult(HTTP_INTERNAL_ERROR, "No security token received.", content); + return; } LLWebSharing::instance().retryOpenIDAuth(); @@ -183,51 +182,18 @@ public: /////////////////////////////////////////////////////////////////////////////// // -class LLWebSharingUploadResponder : public LLHTTPClient::Responder +class LLWebSharingUploadResponder : public LLWebSharingJSONResponder { LOG_CLASS(LLWebSharingUploadResponder); -public: - /// Overrides the default LLSD parsing behaviour, to allow parsing a JSON response. - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) - { -/* - // Dump the body, for debugging. - - LLBufferStream istr1(channels, buffer.get()); - std::ostringstream ostr; - std::string body; - - while (istr1.good()) - { - char buf[1024]; - istr1.read(buf, sizeof(buf)); - body.append(buf, istr1.gcount()); - } - LL_DEBUGS("WebSharing") << body << LL_ENDL; -*/ - LLSD content; - LLBufferStream istr(channels, buffer.get()); - LLPointer parser = new LLSDNotationParser(); - - if (parser->parse(istr, content, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE) - { - LL_WARNS("WebSharing") << "Failed to deserialize LLSD from JSON response. " << " [" << status << "]: " << reason << LL_ENDL; - } - else - { - completed(status, reason, content); - } - } - - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content) +private: + virtual void httpFailure() { - LL_WARNS("WebSharing") << "Error [status:" << status << "]: " << content << LL_ENDL; + LL_WARNS("WebSharing") << dumpResponse() << LL_ENDL; } - virtual void result(const LLSD& content) + virtual void httpSuccess() { + const LLSD& content = getContent(); if (content[0].has("result") && content[0].has("id") && content[0]["id"].asString() == "newMediaItem") { @@ -235,8 +201,8 @@ public: } else { - LL_WARNS("WebSharing") << "Error [" << content[0]["code"].asString() - << "]: " << content[0]["message"].asString() << LL_ENDL; + failureResult(HTTP_INTERNAL_ERROR, "Invalid response content", content); + return; } } }; @@ -333,7 +299,7 @@ void LLWebSharing::sendConfigRequest() LL_DEBUGS("WebSharing") << "Requesting Snapshot Sharing config data from: " << config_url << LL_ENDL; LLSD headers = LLSD::emptyMap(); - headers["Accept"] = "application/json"; + headers[HTTP_HEADER_ACCEPT] = HTTP_CONTENT_JSON; LLHTTPClient::get(config_url, new LLWebSharingConfigResponder(), headers); } @@ -344,8 +310,8 @@ void LLWebSharing::sendOpenIDAuthRequest() LL_DEBUGS("WebSharing") << "Starting OpenID Auth: " << auth_url << LL_ENDL; LLSD headers = LLSD::emptyMap(); - headers["Cookie"] = mOpenIDCookie; - headers["Accept"] = "*/*"; + headers[HTTP_HEADER_COOKIE] = mOpenIDCookie; + headers[HTTP_HEADER_ACCEPT] = "*/*"; // Send request, successful login will trigger fetching a security token. LLHTTPClient::get(auth_url, new LLWebSharingOpenIDAuthResponder(), headers); @@ -371,10 +337,10 @@ void LLWebSharing::sendSecurityTokenRequest() LL_DEBUGS("WebSharing") << "Fetching security token from: " << token_url << LL_ENDL; LLSD headers = LLSD::emptyMap(); - headers["Cookie"] = mSessionCookie; + headers[HTTP_HEADER_COOKIE] = mSessionCookie; - headers["Accept"] = "application/json"; - headers["Content-Type"] = "application/json"; + headers[HTTP_HEADER_ACCEPT] = HTTP_CONTENT_JSON; + headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_JSON; std::ostringstream body; body << "{ \"gadgets\": [{ \"url\":\"" @@ -400,10 +366,10 @@ void LLWebSharing::sendUploadRequest() static const std::string BOUNDARY("------------abcdef012345xyZ"); LLSD headers = LLSD::emptyMap(); - headers["Cookie"] = mSessionCookie; + headers[HTTP_HEADER_COOKIE] = mSessionCookie; - headers["Accept"] = "application/json"; - headers["Content-Type"] = "multipart/form-data; boundary=" + BOUNDARY; + headers[HTTP_HEADER_ACCEPT] = HTTP_CONTENT_JSON; + headers[HTTP_HEADER_CONTENT_TYPE] = "multipart/form-data; boundary=" + BOUNDARY; std::ostringstream body; body << "--" << BOUNDARY << "\r\n" diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp index 93eba5b604..3bedfbe502 100644 --- a/indra/newview/llwlhandlers.cpp +++ b/indra/newview/llwlhandlers.cpp @@ -95,8 +95,9 @@ LLEnvironmentRequestResponder::LLEnvironmentRequestResponder() { mID = ++sCount; } -/*virtual*/ void LLEnvironmentRequestResponder::result(const LLSD& unvalidated_content) +/*virtual*/ void LLEnvironmentRequestResponder::httpSuccess() { + const LLSD& unvalidated_content = getContent(); LL_INFOS("WindlightCaps") << "Received region windlight settings" << LL_ENDL; if (mID != sCount) @@ -122,10 +123,10 @@ LLEnvironmentRequestResponder::LLEnvironmentRequestResponder() LLEnvManagerNew::getInstance()->onRegionSettingsResponse(unvalidated_content); } /*virtual*/ -void LLEnvironmentRequestResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLEnvironmentRequestResponder::httpFailure() { - LL_INFOS("WindlightCaps") << "Got an error, not using region windlight... [status:" - << status << "]: " << content << LL_ENDL; + LL_WARNS("WindlightCaps") << "Got an error, not using region windlight... " + << dumpResponse() << LL_ENDL; LLEnvManagerNew::getInstance()->onRegionSettingsResponse(LLSD()); } @@ -169,8 +170,14 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content) /**** * LLEnvironmentApplyResponder ****/ -/*virtual*/ void LLEnvironmentApplyResponder::result(const LLSD& content) +/*virtual*/ void LLEnvironmentApplyResponder::httpSuccess() { + const LLSD& content = getContent(); + if (!content.isMap() || !content.has("regionID")) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } if (content["regionID"].asUUID() != gAgent.getRegion()->getRegionID()) { LL_WARNS("WindlightCaps") << "No longer in the region where data was sent (currently " @@ -185,7 +192,7 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content) } else { - LL_WARNS("WindlightCaps") << "Region couldn't apply windlight settings! Reason from sim: " << content["fail_reason"].asString() << LL_ENDL; + LL_WARNS("WindlightCaps") << "Region couldn't apply windlight settings! " << dumpResponse() << LL_ENDL; LLSD args(LLSD::emptyMap()); args["FAIL_REASON"] = content["fail_reason"].asString(); LLNotificationsUtil::add("WLRegionApplyFail", args); @@ -193,14 +200,14 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content) } } /*virtual*/ -void LLEnvironmentApplyResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) +void LLEnvironmentApplyResponder::httpFailure() { - LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region! [status:" - << status << "]: " << content << LL_ENDL; + LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region! " + << dumpResponse() << LL_ENDL; LLSD args(LLSD::emptyMap()); std::stringstream msg; - msg << reason << " (Code " << status << ")"; + msg << getReason() << " (Code " << getStatus() << ")"; args["FAIL_REASON"] = msg.str(); LLNotificationsUtil::add("WLRegionApplyFail", args); } diff --git a/indra/newview/llwlhandlers.h b/indra/newview/llwlhandlers.h index 598ce6d52a..089c799da7 100644 --- a/indra/newview/llwlhandlers.h +++ b/indra/newview/llwlhandlers.h @@ -45,9 +45,9 @@ private: class LLEnvironmentRequestResponder: public LLHTTPClient::Responder { LOG_CLASS(LLEnvironmentRequestResponder); -public: - virtual void result(const LLSD& content); - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); +private: + /* virtual */ void httpSuccess(); + /* virtual */ void httpFailure(); private: friend class LLEnvironmentRequest; @@ -72,7 +72,7 @@ private: class LLEnvironmentApplyResponder: public LLHTTPClient::Responder { LOG_CLASS(LLEnvironmentApplyResponder); -public: +private: /* * Expecting reply from sim in form of: * { @@ -87,10 +87,10 @@ public: * fail_reason : string * } */ - virtual void result(const LLSD& content); + /* virtual */ void httpSuccess(); - // non-200 errors only - virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content); + // non-2xx errors only + /* virtual */ void httpFailure(); private: friend class LLEnvironmentApply; diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 0da70d398b..604e08161e 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -331,7 +331,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) This might help with bug #503 */ mCurlRequest->setopt(CURLOPT_DNS_CACHE_TIMEOUT, -1); - mCurlRequest->slist_append("Content-Type: text/xml"); + mCurlRequest->slist_append(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML); if (useGzip) { diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp index 41cb344808..01195d1269 100644 --- a/indra/newview/tests/llmediadataclient_test.cpp +++ b/indra/newview/tests/llmediadataclient_test.cpp @@ -33,7 +33,7 @@ #include "llsdserialize.h" #include "llsdutil.h" #include "llerrorcontrol.h" -#include "llhttpstatuscodes.h" +#include "llhttpconstants.h" #include "../llmediadataclient.h" #include "../llvovolume.h" @@ -128,7 +128,7 @@ void LLHTTPClient::post( { LLSD content; content["reason"] = "fake reason"; - responder->errorWithContent(HTTP_SERVICE_UNAVAILABLE, "fake reason", content); + responder->failureResult(HTTP_SERVICE_UNAVAILABLE, "fake reason", content); return; } else if (url == FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR) @@ -136,8 +136,8 @@ void LLHTTPClient::post( LLSD error; error["code"] = LLObjectMediaNavigateClient::ERROR_PERMISSION_DENIED_CODE; result["error"] = error; - } - responder->result(result); + } + responder->successResult(result); } const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f; diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp index ed66066b0a..c49b0350e9 100644 --- a/indra/newview/tests/llremoteparcelrequest_test.cpp +++ b/indra/newview/tests/llremoteparcelrequest_test.cpp @@ -40,12 +40,14 @@ namespace { LLCurl::Responder::Responder() { } LLCurl::Responder::~Responder() { } -void LLCurl::Responder::error(U32,std::string const &) { } -void LLCurl::Responder::result(LLSD const &) { } -void LLCurl::Responder::errorWithContent(U32 status,std::string const &,LLSD const &) { } -void LLCurl::Responder::completedRaw(U32 status, std::string const &, LLChannelDescriptors const &,boost::shared_ptr const &) { } -void LLCurl::Responder::completed(U32 status, std::string const &, LLSD const &) { } -void LLCurl::Responder::completedHeader(U32 status, std::string const &, LLSD const &) { } +void LLCurl::Responder::httpFailure() { } +void LLCurl::Responder::httpSuccess() { } +void LLCurl::Responder::httpCompleted() { } +void LLCurl::Responder::failureResult(S32 status, const std::string& reason, const LLSD& content) { } +void LLCurl::Responder::successResult(const LLSD& content) { } +void LLCurl::Responder::completeResult(S32 status, const std::string& reason, const LLSD& content) { } +std::string LLCurl::Responder::dumpResponse() const { return "(failure)"; } +void LLCurl::Responder::completedRaw(LLChannelDescriptors const &,boost::shared_ptr const &) { } void LLMessageSystem::getF32(char const *,char const *,F32 &,S32) { } void LLMessageSystem::getU8(char const *,char const *,U8 &,S32) { } void LLMessageSystem::getS32(char const *,char const *,S32 &,S32) { } @@ -85,7 +87,7 @@ namespace tut virtual void setParcelID(const LLUUID& parcel_id) { } - virtual void setErrorStatus(U32 status, const std::string& reason) { } + virtual void setErrorStatus(S32 status, const std::string& reason) { } bool mProcessed; }; diff --git a/indra/newview/tests/lltranslate_test.cpp b/indra/newview/tests/lltranslate_test.cpp index fd9527d631..b28eb5db43 100644 --- a/indra/newview/tests/lltranslate_test.cpp +++ b/indra/newview/tests/lltranslate_test.cpp @@ -34,6 +34,8 @@ #include "lltrans.h" #include "llui.h" +#include "../../llmessage/llhttpconstants.cpp" + static const std::string GOOGLE_VALID_RESPONSE1 = "{\ \"data\": {\ @@ -300,12 +302,10 @@ std::string LLControlGroup::getString(const std::string& name) { return "dummy"; LLControlGroup::~LLControlGroup() {} LLCurl::Responder::Responder() {} -void LLCurl::Responder::completedHeader(U32, std::string const&, LLSD const&) {} -void LLCurl::Responder::completedRaw(U32, const std::string&, const LLChannelDescriptors&, const LLIOPipe::buffer_ptr_t& buffer) {} -void LLCurl::Responder::completed(U32, std::string const&, LLSD const&) {} -void LLCurl::Responder::error(U32, std::string const&) {} -void LLCurl::Responder::errorWithContent(U32, std::string const&, LLSD const&) {} -void LLCurl::Responder::result(LLSD const&) {} +void LLCurl::Responder::httpFailure() { } +void LLCurl::Responder::httpSuccess() { } +void LLCurl::Responder::httpCompleted() { } +void LLCurl::Responder::completedRaw(LLChannelDescriptors const &,boost::shared_ptr const &) { } LLCurl::Responder::~Responder() {} void LLHTTPClient::get(const std::string&, const LLSD&, ResponderPtr, const LLSD&, const F32) {} -- cgit v1.2.3 From 626cb6319945f6ff8feee2aec862924581a66056 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Tue, 19 Mar 2013 20:19:40 +0000 Subject: Fixing booking issues in inventory background fetching (especially when caps are not resolved) --- indra/newview/llinventorymodelbackgroundfetch.cpp | 64 ++++++++--------------- 1 file changed, 22 insertions(+), 42 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index e1537033f9..01b0e647a9 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -1,6 +1,6 @@ /** - * @file llinventorymodel.cpp - * @brief Implementation of the inventory model used to track agent inventory. + * @file llinventorymodelbackgroundfetch.cpp + * @brief Implementation of background fetching of inventory. * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code @@ -365,25 +365,19 @@ class LLInventoryModelFetchItemResponder : public LLInventoryModel::fetchInvento { LOG_CLASS(LLInventoryModelFetchItemResponder); public: - LLInventoryModelFetchItemResponder(const LLSD& request_sd) : LLInventoryModel::fetchInventoryResponder(request_sd) {}; + LLInventoryModelFetchItemResponder(const LLSD& request_sd) : + LLInventoryModel::fetchInventoryResponder(request_sd) + { + LLInventoryModelBackgroundFetch::instance().incrFetchCount(1); + } private: - /* virtual */ void httpSuccess(); - /* virtual */ void httpFailure(); + /* virtual */ void httpCompleted() + { + LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); + LLInventoryModel::fetchInventoryResponder::httpCompleted(); + } }; -void LLInventoryModelFetchItemResponder::httpSuccess() -{ - LLInventoryModel::fetchInventoryResponder::httpSuccess(); - LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); -} - -void LLInventoryModelFetchItemResponder::httpFailure() -{ - LLInventoryModel::fetchInventoryResponder::httpFailure(); - LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); -} - - class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder { LOG_CLASS(LLInventoryModelFetchDescendentsResponder); @@ -391,9 +385,16 @@ public: LLInventoryModelFetchDescendentsResponder(const LLSD& request_sd, uuid_vec_t recursive_cats) : mRequestSD(request_sd), mRecursiveCatUUIDs(recursive_cats) - {}; + { + LLInventoryModelBackgroundFetch::instance().incrFetchCount(1); + } //LLInventoryModelFetchDescendentsResponder() {}; private: + /* virtual */ void httpCompleted() + { + LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); + LLHTTPClient::Responder::httpCompleted(); + } /* virtual */ void httpSuccess(); /* virtual */ void httpFailure(); protected: @@ -527,8 +528,6 @@ void LLInventoryModelFetchDescendentsResponder::httpSuccess() << "Error: " << folder_sd["error"].asString() << llendl; } } - - fetcher->incrFetchCount(-1); if (fetcher->isBulkFetchProcessingComplete()) { @@ -545,8 +544,6 @@ void LLInventoryModelFetchDescendentsResponder::httpFailure() llwarns << dumpResponse() << llendl; LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); - fetcher->incrFetchCount(-1); - if (getStatus()==HTTP_INTERNAL_ERROR) // timed out or curl failure { for(LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray(); @@ -595,7 +592,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() (mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches)) { return; // just bail if we are disconnected - } + } U32 item_count=0; U32 folder_count=0; @@ -698,7 +695,6 @@ void LLInventoryModelBackgroundFetch::bulkFetch() std::string url = region->getCapability("FetchInventoryDescendents2"); if ( !url.empty() ) { - mFetchCount++; if (folder_request_body["folders"].size()) { LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats); @@ -711,7 +707,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats); LLHTTPClient::post(url_lib, folder_request_body_lib, fetcher, 300.0); } - } + } } if (item_count) { @@ -719,39 +715,23 @@ void LLInventoryModelBackgroundFetch::bulkFetch() if (item_request_body.size()) { - mFetchCount++; url = region->getCapability("FetchInventory2"); if (!url.empty()) { LLSD body; - body["agent_id"] = gAgent.getID(); body["items"] = item_request_body; LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body)); } - //else - //{ - // LLMessageSystem* msg = gMessageSystem; - // msg->newMessage("FetchInventory"); - // msg->nextBlock("AgentData"); - // msg->addUUID("AgentID", gAgent.getID()); - // msg->addUUID("SessionID", gAgent.getSessionID()); - // msg->nextBlock("InventoryData"); - // msg->addUUID("OwnerID", mPermissions.getOwner()); - // msg->addUUID("ItemID", mUUID); - // gAgent.sendReliableMessage(); - //} } if (item_request_body_lib.size()) { - mFetchCount++; url = region->getCapability("FetchLib2"); if (!url.empty()) { LLSD body; - body["agent_id"] = gAgent.getID(); body["items"] = item_request_body_lib; LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body)); -- cgit v1.2.3 From cfd35b8b22e8043ab14c57f6ee6108cea471a1ab Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Thu, 28 Mar 2013 18:07:54 -0400 Subject: Made a bug that was masking the warning about mismatched caps coming from a region. They could never match because certain capabilities are explicitly not stored when we receive them. * Made mSecondCapabilitiesTracker set capabilities in a way that more closely matches mCapabilities so that they will match up when we get a second cap grant from a region if the caps that were sent are actually the same. * Added more logging around setting a region's seed capability. * Also added a static function in llviewerregion to dump out a CapabilityMap based on the logActiveCapabilities method. Defined the old method in terms of the new static free function. --- indra/newview/app_settings/logcontrol.xml | 4 +- indra/newview/llstartup.cpp | 2 + indra/newview/llviewermessage.cpp | 5 ++ indra/newview/llviewerregion.cpp | 81 +++++++++++++++++++++++-------- indra/newview/llworld.cpp | 2 + 5 files changed, 70 insertions(+), 24 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index c5561166fc..04b3c81602 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -43,9 +43,7 @@ tags Avatar - + CrossingCaps diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 8b71f1067f..e4627b132f 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1279,6 +1279,8 @@ bool idle_startup() LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle); LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL; + LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from init_idle(). Seed cap == " + << gFirstSimSeedCap << LL_ENDL; regionp->setSeedCapability(gFirstSimSeedCap); LL_DEBUGS("AppInit") << "Waiting for seed grant ...." << LL_ENDL; display_startup(); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index f167bd14d8..0178982d45 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3922,6 +3922,8 @@ void process_teleport_finish(LLMessageSystem* msg, void**) gAgent.setTeleportState( LLAgent::TELEPORT_MOVING ); gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["contacting"]); + LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from process_teleport_finish(). Seed cap == " + << seedCap << LL_ENDL; regionp->setSeedCapability(seedCap); // Don't send camera updates to the new region until we're @@ -4176,6 +4178,9 @@ void process_crossed_region(LLMessageSystem* msg, void**) send_complete_agent_movement(sim_host); LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host); + + LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from process_crossed_region(). Seed cap == " + << seedCap << LL_ENDL; regionp->setSeedCapability(seedCap); } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 2286bb09e1..223f754c2e 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -87,6 +87,8 @@ const S32 MAX_CAP_REQUEST_ATTEMPTS = 30; typedef std::map CapabilityMap; +static void logCapabilities(const CapabilityMap &capmap); + class LLViewerRegionImpl { public: LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host) @@ -321,17 +323,36 @@ private: if ( regionp->getRegionImpl()->mCapabilities.size() != regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() ) { LL_WARNS2("AppInit", "Capabilities") - << "Sim sent duplicate seed caps that differs in size - most likely content." << LL_ENDL; - //todo#add cap debug versus original check? - /*CapabilityMap::const_iterator iter = regionp->getRegionImpl()->mCapabilities.begin(); - while (iter!=regionp->getRegionImpl()->mCapabilities.end() ) - { - llinfos<<"BaseCapabilitiesCompleteTracker Original "<first<<" "<< iter->second<getRegionImpl()->mCapabilities.size() + << " mSecondCapabilitiesTracker == " << regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() + << LL_ENDL; + + //LL_WARNS2("AppInit", "Capabilities") + // << "Initial Base capabilities: " << LL_ENDL; + + //logCapabilities(regionp->getRegionImpl()->mCapabilities); + + //LL_WARNS2("AppInit", "Capabilities") + // << "Latest base capabilities: " << LL_ENDL; + + //logCapabilities(regionp->getRegionImpl()->mSecondCapabilitiesTracker); + + // *TODO + //add cap debug versus original check? + //CapabilityMap::const_iterator iter = regionp->getRegionImpl()->mCapabilities.begin(); + //while (iter!=regionp->getRegionImpl()->mCapabilities.end() ) + //{ + // llinfos<<"BaseCapabilitiesCompleteTracker Original "<first<<" "<< iter->second<getRegionImplNC()->mSecondCapabilitiesTracker.clear(); } + else + { + LL_DEBUGS("CrossingCaps") << "Sim sent multiple base cap grants with matching sizes." << LL_ENDL; + } } @@ -1671,7 +1692,9 @@ void LLViewerRegion::setSeedCapability(const std::string& url) { if (getCapability("Seed") == url) { - //llwarns << "Ignoring duplicate seed capability" << llendl; + setCapabilityDebug("Seed", url); + LL_DEBUGS("CrossingCaps") << "Received duplicate seed capability, posting to seed " << + url << llendl; //Instead of just returning we build up a second set of seed caps and compare them //to the "original" seed cap received and determine why there is problem! LLSD capabilityNames = LLSD::emptyArray(); @@ -1821,7 +1844,16 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u void LLViewerRegion::setCapabilityDebug(const std::string& name, const std::string& url) { - mImpl->mSecondCapabilitiesTracker[name] = url; + // Continue to not add certain caps, as we do in setCapability. This is so they match up when we check them later. + if ( ! ( name == "EventQueueGet" || name == "UntrustedSimulatorMessage" || name == "SimulatorFeatures" ) ) + { + mImpl->mSecondCapabilitiesTracker[name] = url; + if(name == "GetTexture") + { + mHttpUrl = url ; + } + } + } bool LLViewerRegion::isSpecialCapabilityName(const std::string &name) @@ -1872,16 +1904,7 @@ boost::signals2::connection LLViewerRegion::setCapabilitiesReceivedCallback(cons void LLViewerRegion::logActiveCapabilities() const { - int count = 0; - CapabilityMap::const_iterator iter; - for (iter = mImpl->mCapabilities.begin(); iter != mImpl->mCapabilities.end(); ++iter, ++count) - { - if (!iter->second.empty()) - { - llinfos << iter->first << " URL is " << iter->second << llendl; - } - } - llinfos << "Dumped " << count << " entries." << llendl; + logCapabilities(mImpl->mCapabilities); } LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type) @@ -1965,3 +1988,19 @@ bool LLViewerRegion::dynamicPathfindingEnabled() const mSimulatorFeatures["DynamicPathfindingEnabled"].asBoolean()); } +/* Static Functions */ + +void logCapabilities(const CapabilityMap &capmap) +{ + S32 count = 0; + CapabilityMap::const_iterator iter; + for (iter = capmap.begin(); iter != capmap.end(); ++iter, ++count) + { + if (!iter->second.empty()) + { + llinfos << "logCapabilities: " << iter->first << " URL is " << iter->second << llendl; + } + } + llinfos << "logCapabilities: Dumped " << count << " entries." << llendl; +} + diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 793becf0c8..d9da639af9 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -1065,6 +1065,8 @@ public: << sim << llendl; return; } + LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from LLEstablishAgentCommunication::post. Seed cap == " + << input["body"]["seed-capability"] << LL_ENDL; regionp->setSeedCapability(input["body"]["seed-capability"]); } }; -- cgit v1.2.3 From 298660a5f15e08ef00c240330553f3228db5437f Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Mon, 1 Apr 2013 11:59:27 -0400 Subject: Backed out accidentally committed change to logcontrol.xml. --- indra/newview/app_settings/logcontrol.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 04b3c81602..c5561166fc 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -43,7 +43,9 @@ tags Avatar - CrossingCaps + -- cgit v1.2.3 From 9927963ac9d7ef19db96e8d5ffa04c04d0e3b803 Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Mon, 1 Apr 2013 20:10:39 -0400 Subject: If we get more caps from a subsequent grant for a region, go ahead and use them. This is a hack that should be safe to remove after SH-3895 is fixed everywhere on the sim side. --- indra/newview/llviewerregion.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 223f754c2e..f4b6ff318b 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -347,12 +347,23 @@ private: // ++iter; //} - regionp->getRegionImplNC()->mSecondCapabilitiesTracker.clear(); + if (regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() > regionp->getRegionImpl()->mCapabilities.size() ) + { + // *HACK Since we were granted more base capabilities in this grant request than the initial, replace + // the old with the new. This shouldn't happen i.e. we should always get the same capabilities from a + // sim. The simulator fix from SH-3895 should prevent it from happening, at least in the case of the + // inventory api capability grants. + + // Need to clear a std::map before copying into it because old keys take precedence. + regionp->getRegionImplNC()->mCapabilities.clear(); + regionp->getRegionImplNC()->mCapabilities = regionp->getRegionImpl()->mSecondCapabilitiesTracker; + } } else { LL_DEBUGS("CrossingCaps") << "Sim sent multiple base cap grants with matching sizes." << LL_ENDL; } + regionp->getRegionImplNC()->mSecondCapabilitiesTracker.clear(); } -- cgit v1.2.3 From 557adcabb925acbcc79f39f76f7cb74b6202a8da Mon Sep 17 00:00:00 2001 From: Logan Dethrow Date: Tue, 2 Apr 2013 19:51:45 +0000 Subject: Renamed logCapabilites static function to log_capabilities in llviewerregion.cpp to better match coding standard. --- indra/newview/llviewerregion.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index f4b6ff318b..f0d81c599c 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -87,7 +87,7 @@ const S32 MAX_CAP_REQUEST_ATTEMPTS = 30; typedef std::map CapabilityMap; -static void logCapabilities(const CapabilityMap &capmap); +static void log_capabilities(const CapabilityMap &capmap); class LLViewerRegionImpl { public: @@ -331,12 +331,12 @@ private: //LL_WARNS2("AppInit", "Capabilities") // << "Initial Base capabilities: " << LL_ENDL; - //logCapabilities(regionp->getRegionImpl()->mCapabilities); + //log_capabilities(regionp->getRegionImpl()->mCapabilities); //LL_WARNS2("AppInit", "Capabilities") // << "Latest base capabilities: " << LL_ENDL; - //logCapabilities(regionp->getRegionImpl()->mSecondCapabilitiesTracker); + //log_capabilities(regionp->getRegionImpl()->mSecondCapabilitiesTracker); // *TODO //add cap debug versus original check? @@ -1915,7 +1915,7 @@ boost::signals2::connection LLViewerRegion::setCapabilitiesReceivedCallback(cons void LLViewerRegion::logActiveCapabilities() const { - logCapabilities(mImpl->mCapabilities); + log_capabilities(mImpl->mCapabilities); } LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type) @@ -2001,7 +2001,7 @@ bool LLViewerRegion::dynamicPathfindingEnabled() const /* Static Functions */ -void logCapabilities(const CapabilityMap &capmap) +void log_capabilities(const CapabilityMap &capmap) { S32 count = 0; CapabilityMap::const_iterator iter; @@ -2009,9 +2009,9 @@ void logCapabilities(const CapabilityMap &capmap) { if (!iter->second.empty()) { - llinfos << "logCapabilities: " << iter->first << " URL is " << iter->second << llendl; + llinfos << "log_capabilities: " << iter->first << " URL is " << iter->second << llendl; } } - llinfos << "logCapabilities: Dumped " << count << " entries." << llendl; + llinfos << "log_capabilities: Dumped " << count << " entries." << llendl; } -- cgit v1.2.3 From beeefb45269f45ea717f58b30a0985951ae23c20 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Thu, 4 Apr 2013 21:50:45 +0000 Subject: Renaming HTTP_HEADER_* into HTTP_IN_HEADER_* and HTTP_OUT_HEADER_* to make it more clear which header strings should be used for incoming vs outgoing situations. Using constants for commonly used llhttpnode context strings. --- indra/newview/llappearancemgr.cpp | 4 +- indra/newview/llfloaterabout.cpp | 3 +- indra/newview/llfloaterurlentry.cpp | 3 +- indra/newview/llmarketplacefunctions.cpp | 23 +++++------ indra/newview/llmediadataclient.cpp | 4 +- indra/newview/llmeshrepository.cpp | 10 ++--- indra/newview/lltexturefetch.cpp | 6 +-- indra/newview/lltranslate.cpp | 4 +- indra/newview/llviewerdisplayname.cpp | 2 +- indra/newview/llviewermedia.cpp | 34 +++++++--------- indra/newview/llwebprofile.cpp | 11 +++-- indra/newview/llwebsharing.cpp | 69 +++++++++++++++++++++----------- indra/newview/llxmlrpctransaction.cpp | 2 +- 13 files changed, 94 insertions(+), 81 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 43439bac5d..0b85f438bd 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -3008,8 +3008,8 @@ public: #if 0 // *TODO: Honor server Retry-After header. // Status 503 may ask us to wait for a certain amount of time before retrying. - if (!headers.has(HTTP_HEADER_RETRY_AFTER) - || !getSecondsUntilRetryAfter(headers[HTTP_HEADER_RETRY_AFTER].asStringRef(), seconds_to_wait)) + if (!headers.has(HTTP_IN_HEADER_RETRY_AFTER) + || !getSecondsUntilRetryAfter(headers[HTTP_IN_HEADER_RETRY_AFTER].asStringRef(), seconds_to_wait)) #endif { seconds_to_wait = mDelay; diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 63888ace11..801a24f472 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -474,8 +474,7 @@ void LLServerReleaseNotesURLFetcher::httpCompleted() LLFloaterAbout* floater_about = LLFloaterReg::getTypedInstance("sl_about"); if (floater_about) { - const bool check_lower = true; - const std::string& location = getResponseHeader(HTTP_HEADER_LOCATION, check_lower); + const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION); if (location.empty()) { LL_WARNS("ServerReleaseNotes") << "Missing Location header " diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp index 0751c830d5..e26f1e9ea5 100644 --- a/indra/newview/llfloaterurlentry.cpp +++ b/indra/newview/llfloaterurlentry.cpp @@ -59,8 +59,7 @@ public: private: /* virtual */ void httpCompleted() { - const bool check_lower = true; - const std::string& media_type = getResponseHeader(HTTP_HEADER_CONTENT_TYPE, check_lower); + const std::string& media_type = getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE); std::string::size_type idx1 = media_type.find_first_of(";"); std::string mime_type = media_type.substr(0, idx1); diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index bea1d62b93..28e1df725a 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -167,8 +167,7 @@ namespace LLMarketplaceImport protected: /* virtual */ void httpCompleted() { - const bool check_lower = true; - const std::string& set_cookie_string = getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower); + const std::string& set_cookie_string = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE); if (!set_cookie_string.empty()) { @@ -278,10 +277,11 @@ namespace LLMarketplaceImport // Make the headers for the post LLSD headers = LLSD::emptyMap(); - headers[HTTP_HEADER_ACCEPT] = "*/*"; - headers[HTTP_HEADER_COOKIE] = sMarketplaceCookie; - headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML; - headers[HTTP_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent(); + headers[HTTP_OUT_HEADER_ACCEPT] = "*/*"; + headers[HTTP_OUT_HEADER_COOKIE] = sMarketplaceCookie; + // *TODO: Why are we setting Content-Type for a GET request? + headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML; + headers[HTTP_OUT_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent(); if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { @@ -311,12 +311,11 @@ namespace LLMarketplaceImport // Make the headers for the post LLSD headers = LLSD::emptyMap(); - headers[HTTP_HEADER_ACCEPT] = "*/*"; - headers[HTTP_HEADER_CONNECTION] = "Keep-Alive"; - headers[HTTP_HEADER_COOKIE] = sMarketplaceCookie; - // *TODO: Should this be 'application/llsd+xml'? - headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML; - headers[HTTP_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent(); + headers[HTTP_OUT_HEADER_ACCEPT] = "*/*"; + headers[HTTP_OUT_HEADER_CONNECTION] = "Keep-Alive"; + headers[HTTP_OUT_HEADER_COOKIE] = sMarketplaceCookie; + headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML; + headers[HTTP_OUT_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent(); if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index bc1aa087e5..691be13610 100644 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -579,8 +579,8 @@ void LLMediaDataClient::Responder::httpFailure() F32 retry_timeout; #if 0 // *TODO: Honor server Retry-After header. - if (!hasResponseHeader(HTTP_HEADER_RETRY_AFTER) - || !getSecondsUntilRetryAfter(getResponseHeader(HTTP_HEADER_RETRY_AFTER), retry_timeout)) + if (!hasResponseHeader(HTTP_IN_HEADER_RETRY_AFTER) + || !getSecondsUntilRetryAfter(getResponseHeader(HTTP_IN_HEADER_RETRY_AFTER), retry_timeout)) #endif { retry_timeout = mRequest->getRetryTimerDelay(); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 1469dbc346..524467a37e 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -808,7 +808,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) //reading from VFS failed for whatever reason, fetch from sim std::vector headers; - headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); + headers.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) @@ -890,7 +890,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) //reading from VFS failed for whatever reason, fetch from sim std::vector headers; - headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); + headers.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) @@ -971,7 +971,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) //reading from VFS failed for whatever reason, fetch from sim std::vector headers; - headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); + headers.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) @@ -1052,7 +1052,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& c //either cache entry doesn't exist or is corrupt, request header from simulator bool retval = true ; std::vector headers; - headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); + headers.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); std::string http_url = constructUrl(mesh_params.getSculptID()); if (!http_url.empty()) @@ -1127,7 +1127,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, //reading from VFS failed for whatever reason, fetch from sim std::vector headers; - headers.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); + headers.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_OCTET_STREAM); std::string http_url = constructUrl(mesh_id); if (!http_url.empty()) diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 9e9efa7ebd..cc6dc64626 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -2408,9 +2408,9 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mHttpOptions = new LLCore::HttpOptions; mHttpHeaders = new LLCore::HttpHeaders; // *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ? - mHttpHeaders->mHeaders.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C); + mHttpHeaders->mHeaders.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C); mHttpMetricsHeaders = new LLCore::HttpHeaders; - mHttpMetricsHeaders->mHeaders.push_back(HTTP_HEADER_CONTENT_TYPE + ": " + HTTP_CONTENT_LLSD_XML); + mHttpMetricsHeaders->mHeaders.push_back(HTTP_OUT_HEADER_CONTENT_TYPE + ": " + HTTP_CONTENT_LLSD_XML); mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicyDefault(); } @@ -4043,7 +4043,7 @@ void LLTextureFetchDebugger::init() { mHttpHeaders = new LLCore::HttpHeaders; // *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ? - mHttpHeaders->mHeaders.push_back(HTTP_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C); + mHttpHeaders->mHeaders.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C); } } diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index b9840fa3e4..ae934d9f5a 100755 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -394,8 +394,8 @@ void LLTranslate::sendRequest(const std::string& url, LLHTTPClient::ResponderPtr LLVersionInfo::getPatch(), LLVersionInfo::getBuild()); - sHeader.insert(HTTP_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN); - sHeader.insert(HTTP_HEADER_USER_AGENT, user_agent); + sHeader.insert(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN); + sHeader.insert(HTTP_OUT_HEADER_USER_AGENT, user_agent); } LLHTTPClient::get(url, responder, sHeader, REQUEST_TIMEOUT); diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp index 5d94756da3..3f836efdd3 100644 --- a/indra/newview/llviewerdisplayname.cpp +++ b/indra/newview/llviewerdisplayname.cpp @@ -86,7 +86,7 @@ void LLViewerDisplayName::set(const std::string& display_name, const set_name_sl // People API can return localized error messages. Indicate our // language preference via header. LLSD headers; - headers[HTTP_HEADER_ACCEPT_LANGUAGE] = LLUI::getLanguage(); + headers[HTTP_OUT_HEADER_ACCEPT_LANGUAGE] = LLUI::getLanguage(); // People API requires both the old and new value to change a variable. // Our display name will be in cache before the viewer's UI is available diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 8c29a03176..2cec808f19 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -185,8 +185,7 @@ private: llwarns << dumpResponse() << " [headers:" << getResponseHeaders() << "]" << llendl; } - const bool check_lower = true; - const std::string& media_type = getResponseHeader(HTTP_HEADER_CONTENT_TYPE, check_lower); + const std::string& media_type = getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE); std::string::size_type idx1 = media_type.find_first_of(";"); std::string mime_type = media_type.substr(0, idx1); @@ -289,8 +288,7 @@ public: // We don't care about the content of the response, only the Set-Cookie header. LL_DEBUGS("MediaAuth") << dumpResponse() << " [headers:" << getResponseHeaders() << "]" << LL_ENDL; - const bool check_lower = true; - const std::string& cookie = getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower); + const std::string& cookie = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE); // *TODO: What about bad status codes? Does this destroy previous cookies? LLViewerMedia::openIDCookieResponse(cookie); @@ -321,12 +319,10 @@ public: LLSD stripped_content = getResponseHeaders(); // *TODO: Check that this works. - stripped_content.erase(HTTP_HEADER_SET_COOKIE); - stripped_content.erase("set-cookie"); + stripped_content.erase(HTTP_IN_HEADER_SET_COOKIE); LL_WARNS("MediaAuth") << stripped_content << LL_ENDL; - const bool check_lower = true; - const std::string& cookie = getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower); + const std::string& cookie = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE); LL_DEBUGS("MediaAuth") << "cookie = " << cookie << LL_ENDL; // *TODO: What about bad status codes? Does this destroy previous cookies? @@ -1383,12 +1379,12 @@ void LLViewerMedia::removeCookie(const std::string &name, const std::string &dom LLSD LLViewerMedia::getHeaders() { LLSD headers = LLSD::emptyMap(); - headers[HTTP_HEADER_ACCEPT] = "*/*"; + headers[HTTP_OUT_HEADER_ACCEPT] = "*/*"; // *TODO: Should this be 'application/llsd+xml' ? // *TODO: Should this even be set at all? This header is only not overridden in 'GET' methods. - headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML; - headers[HTTP_HEADER_COOKIE] = sOpenIDCookie; - headers[HTTP_HEADER_USER_AGENT] = getCurrentUserAgent(); + headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML; + headers[HTTP_OUT_HEADER_COOKIE] = sOpenIDCookie; + headers[HTTP_OUT_HEADER_USER_AGENT] = getCurrentUserAgent(); return headers; } @@ -1429,9 +1425,9 @@ void LLViewerMedia::setOpenIDCookie() // Do a web profile get so we can store the cookie LLSD headers = LLSD::emptyMap(); - headers[HTTP_HEADER_ACCEPT] = "*/*"; - headers[HTTP_HEADER_COOKIE] = sOpenIDCookie; - headers[HTTP_HEADER_USER_AGENT] = getCurrentUserAgent(); + headers[HTTP_OUT_HEADER_ACCEPT] = "*/*"; + headers[HTTP_OUT_HEADER_COOKIE] = sOpenIDCookie; + headers[HTTP_OUT_HEADER_USER_AGENT] = getCurrentUserAgent(); std::string profile_url = getProfileURL(""); LLURL raw_profile_url( profile_url.c_str() ); @@ -1461,9 +1457,9 @@ void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string LLSD headers = LLSD::emptyMap(); // Keep LLHTTPClient from adding an "Accept: application/llsd+xml" header - headers[HTTP_HEADER_ACCEPT] = "*/*"; + headers[HTTP_OUT_HEADER_ACCEPT] = "*/*"; // and use the expected content-type for a post, instead of the LLHTTPClient::postRaw() default of "application/octet-stream" - headers[HTTP_HEADER_CONTENT_TYPE] = "application/x-www-form-urlencoded"; + headers[HTTP_OUT_HEADER_CONTENT_TYPE] = "application/x-www-form-urlencoded"; // postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here. size_t size = openid_token.size(); @@ -2631,9 +2627,9 @@ void LLViewerMediaImpl::navigateInternal() // Accept: application/llsd+xml // which is really not what we want. LLSD headers = LLSD::emptyMap(); - headers[HTTP_HEADER_ACCEPT] = "*/*"; + headers[HTTP_OUT_HEADER_ACCEPT] = "*/*"; // Allow cookies in the response, to prevent a redirect loop when accessing join.secondlife.com - headers[HTTP_HEADER_COOKIE] = ""; + headers[HTTP_OUT_HEADER_COOKIE] = ""; LLHTTPClient::getHeaderOnly( mMediaURL, new LLMimeDiscoveryResponder(this), headers, 10.0f); } else if("data" == scheme || "file" == scheme || "about" == scheme) diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp index ee78ba20cb..567138e160 100644 --- a/indra/newview/llwebprofile.cpp +++ b/indra/newview/llwebprofile.cpp @@ -167,9 +167,8 @@ public: if (getStatus() == HTTP_SEE_OTHER) { LLSD headers = LLViewerMedia::getHeaders(); - headers[HTTP_HEADER_COOKIE] = LLWebProfile::getAuthCookie(); - const bool check_lower=true; - const std::string& redir_url = getResponseHeader(HTTP_HEADER_LOCATION, check_lower); + headers[HTTP_OUT_HEADER_COOKIE] = LLWebProfile::getAuthCookie(); + const std::string& redir_url = getResponseHeader(HTTP_IN_HEADER_LOCATION); if (redir_url.empty()) { llwarns << "Received empty redirection URL " << dumpResponse() << llendl; @@ -207,7 +206,7 @@ void LLWebProfile::uploadImage(LLPointer image, const std::str LL_DEBUGS("Snapshots") << "Requesting " << config_url << llendl; LLSD headers = LLViewerMedia::getHeaders(); - headers[HTTP_HEADER_COOKIE] = getAuthCookie(); + headers[HTTP_OUT_HEADER_COOKIE] = getAuthCookie(); LLHTTPClient::get(config_url, new LLWebProfileResponders::ConfigResponder(image), headers); } @@ -231,8 +230,8 @@ void LLWebProfile::post(LLPointer image, const LLSD& config, c const std::string boundary = "----------------------------0123abcdefab"; LLSD headers = LLViewerMedia::getHeaders(); - headers[HTTP_HEADER_COOKIE] = getAuthCookie(); - headers[HTTP_HEADER_CONTENT_TYPE] = "multipart/form-data; boundary=" + boundary; + headers[HTTP_OUT_HEADER_COOKIE] = getAuthCookie(); + headers[HTTP_OUT_HEADER_CONTENT_TYPE] = "multipart/form-data; boundary=" + boundary; std::ostringstream body; diff --git a/indra/newview/llwebsharing.cpp b/indra/newview/llwebsharing.cpp index ba536ac582..7036162014 100644 --- a/indra/newview/llwebsharing.cpp +++ b/indra/newview/llwebsharing.cpp @@ -55,25 +55,47 @@ public: const LLIOPipe::buffer_ptr_t& buffer) { LLBufferStream istr(channels, buffer.get()); + // *TODO: LLSD notation is not actually JSON. LLPointer parser = new LLSDNotationParser(); - if (parser->parse(istr, mContent, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE) + std::string debug_body("(empty)"); + bool parsed=true; + if (EOF == istr.peek()) { - if (HTTP_CONTENT_JSON == getResponseHeader(HTTP_HEADER_CONTENT_TYPE)) + parsed=false; + } + // Try to parse body as llsd, no matter what 'content-type' says. + else if (parser->parse(istr, mContent, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE) + { + parsed=false; + char body[1025]; + body[1024] = '\0'; + istr.seekg(0, std::ios::beg); + istr.get(body,1024); + if (strlen(body) > 0) { - mStatus = HTTP_INTERNAL_ERROR; - mReason = "Failed to deserialize LLSD from JSON response."; - char body[1025]; - body[1024] = '\0'; - istr.seekg(0, std::ios::beg); - istr.get(body,1024); - if (strlen(body) > 0) - { - mContent["body"] = body; - } + mContent = body; + debug_body = body; } } + // Only emit a warning if we failed to parse when 'content-type' == 'application/json' + if (!parsed && (HTTP_CONTENT_JSON == getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE))) + { + llwarns << "Failed to deserialize LLSD from JSON response. " << getURL() + << " [status:" << mStatus << "] " + << "(" << mReason << ") body: " << debug_body << llendl; + } + + if (!parsed) + { + // *TODO: This isn't necessarily the server's fault. Using a 5xx code + // isn't really appropriate here. + // Also, this hides the actual status returned by the server.... + mStatus = HTTP_INTERNAL_ERROR; + mReason = "Failed to deserialize LLSD from JSON response."; + } + httpCompleted(); } }; @@ -132,11 +154,10 @@ private: virtual void httpSuccess() { - const bool check_lower=true; - if (hasResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower)) + if (hasResponseHeader(HTTP_IN_HEADER_SET_COOKIE)) { // OpenID request succeeded and returned a session cookie. - LLWebSharing::instance().receiveSessionCookie(getResponseHeader(HTTP_HEADER_SET_COOKIE, check_lower)); + LLWebSharing::instance().receiveSessionCookie(getResponseHeader(HTTP_IN_HEADER_SET_COOKIE)); } } }; @@ -299,7 +320,7 @@ void LLWebSharing::sendConfigRequest() LL_DEBUGS("WebSharing") << "Requesting Snapshot Sharing config data from: " << config_url << LL_ENDL; LLSD headers = LLSD::emptyMap(); - headers[HTTP_HEADER_ACCEPT] = HTTP_CONTENT_JSON; + headers[HTTP_OUT_HEADER_ACCEPT] = HTTP_CONTENT_JSON; LLHTTPClient::get(config_url, new LLWebSharingConfigResponder(), headers); } @@ -310,8 +331,8 @@ void LLWebSharing::sendOpenIDAuthRequest() LL_DEBUGS("WebSharing") << "Starting OpenID Auth: " << auth_url << LL_ENDL; LLSD headers = LLSD::emptyMap(); - headers[HTTP_HEADER_COOKIE] = mOpenIDCookie; - headers[HTTP_HEADER_ACCEPT] = "*/*"; + headers[HTTP_OUT_HEADER_COOKIE] = mOpenIDCookie; + headers[HTTP_OUT_HEADER_ACCEPT] = "*/*"; // Send request, successful login will trigger fetching a security token. LLHTTPClient::get(auth_url, new LLWebSharingOpenIDAuthResponder(), headers); @@ -337,10 +358,10 @@ void LLWebSharing::sendSecurityTokenRequest() LL_DEBUGS("WebSharing") << "Fetching security token from: " << token_url << LL_ENDL; LLSD headers = LLSD::emptyMap(); - headers[HTTP_HEADER_COOKIE] = mSessionCookie; + headers[HTTP_OUT_HEADER_COOKIE] = mSessionCookie; - headers[HTTP_HEADER_ACCEPT] = HTTP_CONTENT_JSON; - headers[HTTP_HEADER_CONTENT_TYPE] = HTTP_CONTENT_JSON; + headers[HTTP_OUT_HEADER_ACCEPT] = HTTP_CONTENT_JSON; + headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_JSON; std::ostringstream body; body << "{ \"gadgets\": [{ \"url\":\"" @@ -366,10 +387,10 @@ void LLWebSharing::sendUploadRequest() static const std::string BOUNDARY("------------abcdef012345xyZ"); LLSD headers = LLSD::emptyMap(); - headers[HTTP_HEADER_COOKIE] = mSessionCookie; + headers[HTTP_OUT_HEADER_COOKIE] = mSessionCookie; - headers[HTTP_HEADER_ACCEPT] = HTTP_CONTENT_JSON; - headers[HTTP_HEADER_CONTENT_TYPE] = "multipart/form-data; boundary=" + BOUNDARY; + headers[HTTP_OUT_HEADER_ACCEPT] = HTTP_CONTENT_JSON; + headers[HTTP_OUT_HEADER_CONTENT_TYPE] = "multipart/form-data; boundary=" + BOUNDARY; std::ostringstream body; body << "--" << BOUNDARY << "\r\n" diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 604e08161e..7c5f8be1b5 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -331,7 +331,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) This might help with bug #503 */ mCurlRequest->setopt(CURLOPT_DNS_CACHE_TIMEOUT, -1); - mCurlRequest->slist_append(HTTP_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML); + mCurlRequest->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML); if (useGzip) { -- cgit v1.2.3 From 0a6a5f63b45bf3d97c7926b8d415b0b3885f64a1 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 5 Apr 2013 13:44:33 -0400 Subject: SH-4061 WIP - spelling fix, allow un-set of missing asset flag for textures --- indra/newview/llviewertexture.cpp | 44 ++++++++++++++++++++++++--------------- indra/newview/llviewertexture.h | 2 +- indra/newview/llvoavatar.cpp | 6 +++--- indra/newview/llvoavatar.h | 2 +- indra/newview/llvoavatarself.cpp | 2 +- 5 files changed, 33 insertions(+), 23 deletions(-) mode change 100644 => 100755 indra/newview/llviewertexture.cpp mode change 100644 => 100755 indra/newview/llviewertexture.h (limited to 'indra/newview') diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp old mode 100644 new mode 100755 index eb6c453e76..500a6c8869 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -2005,29 +2005,39 @@ void LLViewerFetchedTexture::forceToDeleteRequest() mDesiredDiscardLevel = getMaxDiscardLevel() + 1; } -void LLViewerFetchedTexture::setIsMissingAsset() +void LLViewerFetchedTexture::setIsMissingAsset(bool is_missing) { - if (mUrl.empty()) + if (is_missing) { - llwarns << mID << ": Marking image as missing" << llendl; + if (mUrl.empty()) + { + llwarns << mID << ": Marking image as missing" << llendl; + } + else + { + // This may or may not be an error - it is normal to have no + // map tile on an empty region, but bad if we're failing on a + // server bake texture. + if (getFTType() != FTT_MAP_TILE) + { + llwarns << mUrl << ": Marking image as missing" << llendl; + } + } + if (mHasFetcher) + { + LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); + mHasFetcher = FALSE; + mIsFetching = FALSE; + mLastPacketTimer.reset(); + mFetchState = 0; + mFetchPriority = 0; + } } else { - // This may or may not be an error - it is normal to have no - // map tile on an empty region, but bad if we're failing on a - // server bake texture. - llwarns << mUrl << ": Marking image as missing" << llendl; - } - if (mHasFetcher) - { - LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); - mHasFetcher = FALSE; - mIsFetching = FALSE; - mLastPacketTimer.reset(); - mFetchState = 0; - mFetchPriority = 0; + llinfos << mID << ": un-flagging missing asset" << llendl; } - mIsMissingAsset = TRUE; + mIsMissingAsset = is_missing; } void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_callback, diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h old mode 100644 new mode 100755 index f2e1a90713..1f2079104f --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -338,7 +338,7 @@ public: // more data. /*virtual*/ void setKnownDrawSize(S32 width, S32 height); - void setIsMissingAsset(); + void setIsMissingAsset(bool is_missing = true); /*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; } // returns dimensions of original image for local files (before power of two scaling) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 5695fc04b9..a71bb93ba2 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -4408,7 +4408,7 @@ void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerFetchedTexture } const S32 MAX_TEXTURE_UPDATE_INTERVAL = 64 ; //need to call updateTextures() at least every 32 frames. -const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL = S32_MAX ; //frames +const S32 MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL = S32_MAX ; //frames void LLVOAvatar::checkTextureLoading() { static const F32 MAX_INVISIBLE_WAITING_TIME = 15.f ; //seconds @@ -4471,11 +4471,11 @@ const F32 ADDITIONAL_PRI = 0.5f; void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level) { //Note: - //if this function is not called for the last MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL frames, + //if this function is not called for the last MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL frames, //the texture pipeline will stop fetching this texture. imagep->resetTextureStats(); - imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); + imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL); imagep->resetMaxVirtualSizeResetCounter() ; mMaxPixelArea = llmax(pixel_area, mMaxPixelArea); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 85f6f25009..98e8491cb1 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -991,7 +991,7 @@ protected: // Shared with LLVOAvatarSelf }; // LLVOAvatar extern const F32 SELF_ADDITIONAL_PRI; -extern const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL; +extern const S32 MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL; std::string get_sequential_numbered_file_name(const std::string& prefix, const std::string& suffix); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 0404884245..5f9b4a59e7 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2587,7 +2587,7 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe imagep->setBoostLevel(getAvatarBoostLevel()); imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; imagep->resetTextureStats(); - imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); + imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL); imagep->addTextureStats( desired_pixels / texel_area_ratio ); imagep->forceUpdateBindStats() ; if (imagep->getDiscardLevel() < 0) -- cgit v1.2.3 From e16435c37cb7410f3ea4596e30fd232ac558bc71 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 8 Apr 2013 13:26:05 -0400 Subject: SH-4061 WIP - added ability to un-set missing asset, do this in the case of FTT_SERVER_BAKE images. This is needed because 'missing' is not necessarily permanent for such images. --- indra/newview/llpaneloutfitsinventory.cpp | 3 ++- indra/newview/llviewertexture.cpp | 6 +++++- indra/newview/llviewertexture.h | 8 ++++---- indra/newview/llvoavatar.cpp | 4 ++++ 4 files changed, 15 insertions(+), 6 deletions(-) mode change 100644 => 100755 indra/newview/llpaneloutfitsinventory.cpp (limited to 'indra/newview') diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp old mode 100644 new mode 100755 index f90236f6f2..d6c927ab58 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -76,7 +76,8 @@ BOOL LLPanelOutfitsInventory::postBuild() // Fetch your outfits folder so that the links are in memory. // ( This is only necessary if we want to show a warning if a user deletes an item that has a // a link in an outfit, see "ConfirmItemDeleteHasLinks". ) - const LLUUID &outfits_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTFIT, false); + + const LLUUID &outfits_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); if (outfits_cat.notNull()) { LLInventoryModelBackgroundFetch::instance().start(outfits_cat); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 500a6c8869..9cca8a244e 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -2005,8 +2005,12 @@ void LLViewerFetchedTexture::forceToDeleteRequest() mDesiredDiscardLevel = getMaxDiscardLevel() + 1; } -void LLViewerFetchedTexture::setIsMissingAsset(bool is_missing) +void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing) { + if (is_missing == mIsMissingAsset) + { + return; + } if (is_missing) { if (mUrl.empty()) diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 1f2079104f..9465fe180b 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -120,7 +120,7 @@ public: LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ; virtual S8 getType() const; - virtual BOOL isMissingAsset()const ; + virtual BOOL isMissingAsset() const ; virtual void dump(); // debug info to llinfos /*virtual*/ bool bindDefaultImage(const S32 stage = 0) ; @@ -338,8 +338,8 @@ public: // more data. /*virtual*/ void setKnownDrawSize(S32 width, S32 height); - void setIsMissingAsset(bool is_missing = true); - /*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; } + void setIsMissingAsset(BOOL is_missing = true); + /*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; } // returns dimensions of original image for local files (before power of two scaling) // and returns 0 for all asset system images @@ -449,7 +449,7 @@ protected: bool mCanUseHTTP ; //This texture can be fetched through http if true. FTType mFTType; // What category of image is this - map tile, server bake, etc? - mutable S8 mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. + mutable BOOL mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. typedef std::list callback_list_t; S8 mLoadedCallbackDesiredDiscardLevel; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index a71bb93ba2..58da77efbb 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1884,6 +1884,10 @@ LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUU LL_DEBUGS("Avatar") << avString() << "from URL " << url << llendl; result = LLViewerTextureManager::getFetchedTextureFromUrl( url, FTT_SERVER_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid); + if (result->isMissingAsset()) + { + result->setIsMissingAsset(false); + } } else { -- cgit v1.2.3 From 985b7277e824c39275d9a06c6262b6f394b02133 Mon Sep 17 00:00:00 2001 From: prep Date: Mon, 8 Apr 2013 17:10:46 -0400 Subject: WIP SH-4035: confirmation when closing appearance window when changes present --- indra/newview/llfloatersidepanelcontainer.cpp | 16 ++-- indra/newview/llfloatersidepanelcontainer.h | 2 + indra/newview/llinspectavatar.cpp | 5 +- indra/newview/llsidepanelappearance.cpp | 88 +++++++++++++++++++++- indra/newview/llsidepanelappearance.h | 16 +++- indra/newview/llspeakers.cpp | 5 +- .../newview/skins/default/xui/en/notifications.xml | 13 ++++ 7 files changed, 126 insertions(+), 19 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index 5f9556a870..b1f9a18d6f 100644 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -67,15 +67,17 @@ void LLFloaterSidePanelContainer::onClickCloseBtn() if (parent == this ) { LLSidepanelAppearance* panel_appearance = dynamic_cast(getPanel("appearance")); - if ( panel_appearance ) - { - panel_appearance->getWearable()->onClose(); - panel_appearance->showOutfitsInventoryPanel(); - } + panel_appearance->onClose(this); } } - - LLFloater::onClickCloseBtn(); + else + { + LLFloater::onClickCloseBtn(); + } +} +void LLFloaterSidePanelContainer::close() +{ + LLFloater::onClickCloseBtn(); } LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_name, const LLSD& params) diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h index 491723471f..940673b643 100644 --- a/indra/newview/llfloatersidepanelcontainer.h +++ b/indra/newview/llfloatersidepanelcontainer.h @@ -55,6 +55,8 @@ public: LLPanel* openChildPanel(const std::string& panel_name, const LLSD& params); + void close(); + static void showPanel(const std::string& floater_name, const LLSD& key); static void showPanel(const std::string& floater_name, const std::string& panel_name, const LLSD& key); diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 0b3268eb54..6ff16742dd 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -292,10 +292,7 @@ void LLInspectAvatar::processAvatarData(LLAvatarData* data) delete mPropertiesRequest; mPropertiesRequest = NULL; } -/* -prep# - virtual void httpFailure() - */ + void LLInspectAvatar::updateVolumeSlider() { diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 74fa5a87bb..53b5593ac9 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -48,6 +48,8 @@ #include "llviewerregion.h" #include "llvoavatarself.h" #include "llviewerwearable.h" +#include "llnotificationsutil.h" +#include "llfloatersidepanelcontainer.h" static LLRegisterPanelClassWrapper t_appearance("sidepanel_appearance"); @@ -70,13 +72,84 @@ private: LLSidepanelAppearance *mPanel; }; +bool LLSidepanelAppearance::callBackExitWithoutSaveViaBack(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if ( option == 0 ) + { + gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", TRUE); + LLAppearanceMgr::instance().setOutfitDirty( true ); + showOutfitsInventoryPanel(); + LLAppearanceMgr::getInstance()->wearBaseOutfit(); + return true; + } + gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", FALSE); + return false; +} + +bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if ( option == 0 ) + { + gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", TRUE); + mEditWearable->revertChanges(); + LLAppearanceMgr::getInstance()->wearBaseOutfit(); + mLLFloaterSidePanelContainer->close(); + return true; + } + gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", FALSE); + return false; +} + +void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaClose() +{ + if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !LLAppearanceMgr::getInstance()->isOutfitLocked() ) + { + LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this; + LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) ); + } + else + { + showOutfitsInventoryPanel(); + } +} + +void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack() +{ + if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !mSidePanelJustOpened && !LLAppearanceMgr::getInstance()->isOutfitLocked() ) + { + LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this; + LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaBack,pSelf,_1,_2) ); + } + else + { + showOutfitsInventoryPanel(); + } +} + +void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj) +{ + mLLFloaterSidePanelContainer = obj; + if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !LLAppearanceMgr::getInstance()->isOutfitLocked() ) + { + LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this; + LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) ); + } + else + { + mLLFloaterSidePanelContainer->close(); + } +} + LLSidepanelAppearance::LLSidepanelAppearance() : LLPanel(), mFilterSubString(LLStringUtil::null), mFilterEditor(NULL), mOutfitEdit(NULL), mCurrOutfitPanel(NULL), - mOpened(false) + mOpened(false), + mSidePanelJustOpened(true) { LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); outfit_observer.addBOFReplacedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); @@ -85,6 +158,8 @@ LLSidepanelAppearance::LLSidepanelAppearance() : gAgentWearables.addLoadingStartedCallback(boost::bind(&LLSidepanelAppearance::setWearablesLoading, this, true)); gAgentWearables.addLoadedCallback(boost::bind(&LLSidepanelAppearance::setWearablesLoading, this, false)); + + } LLSidepanelAppearance::~LLSidepanelAppearance() @@ -119,8 +194,8 @@ BOOL LLSidepanelAppearance::postBuild() { LLButton* back_btn = mOutfitEdit->getChild("back_btn"); if (back_btn) - { - back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::showOutfitsInventoryPanel, this)); + { + back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack, this)); } } @@ -144,6 +219,7 @@ BOOL LLSidepanelAppearance::postBuild() setVisibleCallback(boost::bind(&LLSidepanelAppearance::onVisibilityChange,this,_2)); + return TRUE; } @@ -183,6 +259,12 @@ void LLSidepanelAppearance::onOpen(const LLSD& key) void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility) { + //handle leaving and subsequent user verification of discarding any unsaved data + if ( mSidePanelJustOpened ) + { + mSidePanelJustOpened = false; + } + LLSD visibility; visibility["visible"] = new_visibility.asBoolean(); visibility["reset_accordion"] = false; diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h index 762f557a80..85e7734567 100644 --- a/indra/newview/llsidepanelappearance.h +++ b/indra/newview/llsidepanelappearance.h @@ -38,9 +38,11 @@ class LLCurrentlyWornFetchObserver; class LLPanelEditWearable; class LLViewerWearable; class LLPanelOutfitsInventory; +class LLFloaterSidePanelContainer; class LLSidepanelAppearance : public LLPanel -{ +{ + LOG_CLASS(LLSidepanelAppearance); public: LLSidepanelAppearance(); @@ -48,6 +50,8 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); + void onClose(LLFloaterSidePanelContainer* obj); + void onClickCloseBtn(); void refreshCurrentOutfitName(const std::string& name = ""); @@ -65,6 +69,11 @@ public: void updateScrollingPanelList(); void updateToVisibility( const LLSD& new_visibility ); LLPanelEditWearable* getWearable(){ return mEditWearable; } + bool callBackExitWithoutSaveViaBack(const LLSD& notification, const LLSD& response); + void onClickConfirmExitWithoutSaveViaBack(); + bool callBackExitWithoutSaveViaClose(const LLSD& notification, const LLSD& response); + void onClickConfirmExitWithoutSaveViaClose(); + private: void onFilterEdit(const std::string& search_string); @@ -85,6 +94,7 @@ private: LLButton* mOpenOutfitBtn; LLButton* mEditAppearanceBtn; LLButton* mNewOutfitBtn; + LLPanel* mCurrOutfitPanel; LLTextBox* mCurrentLookName; @@ -99,6 +109,10 @@ private: // Gets set to true when we're opened for the first time. bool mOpened; + // Set to true if sidepanel has just been opened + bool mSidePanelJustOpened; + LLFloaterSidePanelContainer* mLLFloaterSidePanelContainer; + }; #endif //LL_LLSIDEPANELAPPEARANCE_H diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 3c3c699d17..bf209df863 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -855,10 +855,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update) } } } -/*prep# - virtual void httpFailure() - llwarns << dumpResponse() << llendl; - */ + void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id) { LLPointer speakerp = findSpeaker(speaker_id); diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 105bef7321..2170283af2 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -10030,5 +10030,18 @@ Cannot create large prims that intersect other players. Please re-try when othe name="okignore" yestext="OK"/> + + + + Closing this window will discard any changes you have made. + confirm + + -- cgit v1.2.3 From 4bbcd26941c3be6b83214d0dc45c70f99e474dda Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 8 Apr 2013 18:16:58 -0400 Subject: SH-4061 FIX - texture fetch failures added retry logic and fault injection for testing --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/lltexturefetch.cpp | 28 ++++++++++++++++++++-------- indra/newview/lltexturefetch.h | 2 +- indra/newview/llviewertexture.cpp | 29 ++++++++++++++++++++++------- indra/newview/llviewertexture.h | 1 + 5 files changed, 55 insertions(+), 16 deletions(-) mode change 100644 => 100755 indra/newview/lltexturefetch.h (limited to 'indra/newview') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f66d8fca5b..0b7f99ebc1 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11130,6 +11130,17 @@ Value 0 + TextureFetchFakeFailures + + Comment + Simulate HTTP fetch failures for some server bake textures. + Persist + 1 + Type + Boolean + Value + 0 + TextureFetchSource Comment diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index cc6dc64626..2e6fb160d5 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -388,10 +388,12 @@ public: // Threads: Ttf virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); + void setFakeFailure(bool fake_failure) { mFakeFailure = fake_failure; } + protected: LLTextureFetchWorker(LLTextureFetch* fetcher, FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, - F32 priority, S32 discard, S32 size); + F32 priority, S32 discard, S32 size, bool fake_failure); private: @@ -547,6 +549,7 @@ private: S32 mActiveCount; LLCore::HttpStatus mGetStatus; std::string mGetReason; + bool mFakeFailure; // Work Data LLMutex mWorkMutex; @@ -836,7 +839,8 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, const LLHost& host, // Simulator host F32 priority, // Priority S32 discard, // Desired discard - S32 size) // Desired size + S32 size, // Desired size + bool fake_failure) // For testing, simulate http failure if true. : LLWorkerClass(fetcher, "TextureFetch"), LLCore::HttpHandler(), mState(INIT), @@ -889,7 +893,8 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mHttpHasResource(false), mCacheReadCount(0U), mCacheWriteCount(0U), - mResourceWaitCount(0U) + mResourceWaitCount(0U), + mFakeFailure(fake_failure) { mCanUseNET = mUrl.empty() ; @@ -1519,15 +1524,16 @@ bool LLTextureFetchWorker::doWork(S32 param) { if (http_not_found == mGetStatus) { + llwarns << "Texture missing from server (404): " << mUrl << llendl; + if(mWriteToCacheState == NOT_WRITE) //map tiles { setState(DONE); releaseHttpSemaphore(); - LL_DEBUGS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << llendl; + LL_WARNS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << llendl; return true; // failed, means no map tile on the empty region. } - llwarns << "Texture missing from server (404): " << mUrl << llendl; // roll back to try UDP if (mCanUseNET) @@ -1891,6 +1897,11 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow); } + if (mFakeFailure) + { + llwarns << "For debugging, setting fake failure status for texture " << mID << llendl; + response->setStatus(LLCore::HttpStatus(404)); + } bool success = true; bool partial = false; LLCore::HttpStatus status(response->getStatus()); @@ -2455,7 +2466,7 @@ LLTextureFetch::~LLTextureFetch() } bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, - S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http) + S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http, bool fake_failure) { if(mFetcherLocked) { @@ -2523,7 +2534,8 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const worker->mNeedsAux = needs_aux; worker->setImagePriority(priority); worker->setDesiredDiscard(desired_discard, desired_size); - worker->setCanUseHTTP(can_use_http) ; + worker->setCanUseHTTP(can_use_http); + worker->setFakeFailure(fake_failure); if (!worker->haveWork()) { worker->setState(LLTextureFetchWorker::INIT); @@ -2538,7 +2550,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const } else { - worker = new LLTextureFetchWorker(this, f_type, url, id, host, priority, desired_discard, desired_size); + worker = new LLTextureFetchWorker(this, f_type, url, id, host, priority, desired_discard, desired_size, fake_failure); lockQueue(); // +Mfq mRequestMap[id] = worker; unlockQueue(); // -Mfq diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h old mode 100644 new mode 100755 index 902a3d7a25..b99480d18e --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -78,7 +78,7 @@ public: // Threads: T* (but Tmain mostly) bool createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, - S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http); + S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http, bool fake_failure); // Requests that a fetch operation be deleted from the queue. // If @cancel is true, also stops any I/O operations pending. diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 9cca8a244e..a157600cc9 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -962,6 +962,8 @@ void LLViewerFetchedTexture::init(bool firstinit) // does not contain this image. mIsMissingAsset = FALSE; + mFetchFailureCount = 0; + mLoadedCallbackDesiredDiscardLevel = S8_MAX; mPauseLoadedCallBacks = FALSE ; @@ -1823,12 +1825,18 @@ bool LLViewerFetchedTexture::updateFetch() // We finished but received no data if (current_discard < 0) { - llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority - << " mRawDiscardLevel " << mRawDiscardLevel - << " current_discard " << current_discard - << llendl; - setIsMissingAsset(); - desired_discard = -1; + const S32 MAX_FETCH_FAILURE = 1; + mFetchFailureCount++; + llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount << llendl; + if (getFTType() != FTT_SERVER_BAKE || mFetchFailureCount >= MAX_FETCH_FAILURE) + { + llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority + << " mRawDiscardLevel " << mRawDiscardLevel + << " current_discard " << current_discard + << llendl; + setIsMissingAsset(); + desired_discard = -1; + } } else { @@ -1942,8 +1950,14 @@ bool LLViewerFetchedTexture::updateFetch() // bypass texturefetch directly by pulling from LLTextureCache bool fetch_request_created = false; + bool fake_failure = false; + const bool debug_setting_fake_failures = gSavedSettings.getBOOL("TextureFetchFakeFailures"); + if (getFTType() == FTT_SERVER_BAKE && mFetchFailureCount == 0 && debug_setting_fake_failures) + { + fake_failure = true; + } fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority, - w, h, c, desired_discard, needsAux(), mCanUseHTTP); + w, h, c, desired_discard, needsAux(), mCanUseHTTP, fake_failure); if (fetch_request_created) { @@ -2040,6 +2054,7 @@ void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing) else { llinfos << mID << ": un-flagging missing asset" << llendl; + mFetchFailureCount = 0; } mIsMissingAsset = is_missing; } diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 9465fe180b..320e6f8630 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -450,6 +450,7 @@ protected: FTType mFTType; // What category of image is this - map tile, server bake, etc? mutable BOOL mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. + S32 mFetchFailureCount; // How many times has a fetch failed in a way that suggests the asset is missing? typedef std::list callback_list_t; S8 mLoadedCallbackDesiredDiscardLevel; -- cgit v1.2.3 From 67790d0dd8fec2750906ae3d3fed1e735be6b078 Mon Sep 17 00:00:00 2001 From: "prep@lindenlab.com" Date: Tue, 9 Apr 2013 15:14:51 -0500 Subject: SH-4035: Bug fix to handle closing the panel when editing a specific wearable --- indra/newview/llsidepanelappearance.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 53b5593ac9..3899450804 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -131,7 +131,9 @@ void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack() void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj) { mLLFloaterSidePanelContainer = obj; - if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !LLAppearanceMgr::getInstance()->isOutfitLocked() ) + if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && + !LLAppearanceMgr::getInstance()->isOutfitLocked() || + ( mEditWearable->isAvailable() && mEditWearable->isDirty() ) ) { LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this; LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) ); -- cgit v1.2.3 From 24fa7736dd123429425d91b2b72c3b3b7110b764 Mon Sep 17 00:00:00 2001 From: "prep@lindenlab.com" Date: Tue, 9 Apr 2013 15:30:51 -0500 Subject: SH-4035: Removed unneeded functional call --- indra/newview/llsidepanelappearance.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 3899450804..ae6ceabdaa 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -93,7 +93,6 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica if ( option == 0 ) { gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", TRUE); - mEditWearable->revertChanges(); LLAppearanceMgr::getInstance()->wearBaseOutfit(); mLLFloaterSidePanelContainer->close(); return true; -- cgit v1.2.3 From f78da987913de659367b24e3aa0add2c570f8e1f Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 10 Apr 2013 11:43:48 -0400 Subject: SH-4061 WIP - capture http status codes from requests, restrict SB fetch retries to 5xx errors --- indra/newview/lltexturefetch.cpp | 15 ++++++++++----- indra/newview/lltexturefetch.h | 3 ++- indra/newview/llviewertexture.cpp | 20 ++++++++++++++++---- indra/newview/llviewertexture.h | 4 +++- 4 files changed, 31 insertions(+), 11 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 2e6fb160d5..5a6338d9d8 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -382,6 +382,8 @@ public: void setCanUseHTTP(bool can_use_http) { mCanUseHTTP = can_use_http; } bool getCanUseHTTP() const { return mCanUseHTTP; } + void setUrl(const std::string& url) { mUrl = url; } + LLTextureFetch & getFetcher() { return *mFetcher; } // Inherited from LLCore::HttpHandler @@ -1291,7 +1293,7 @@ bool LLTextureFetchWorker::doWork(S32 param) std::string http_url = region->getHttpUrl() ; if (!http_url.empty()) { - mUrl = http_url + "/?texture_id=" + mID.asString().c_str(); + setUrl(http_url + "/?texture_id=" + mID.asString().c_str()); mWriteToCacheState = CAN_WRITE ; //because this texture has a fixed texture id. } else @@ -1900,7 +1902,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe if (mFakeFailure) { llwarns << "For debugging, setting fake failure status for texture " << mID << llendl; - response->setStatus(LLCore::HttpStatus(404)); + response->setStatus(LLCore::HttpStatus(500)); } bool success = true; bool partial = false; @@ -1918,11 +1920,11 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe // << " offset: " << offset << " length: " << length // << llendl; + std::string reason(status.toString()); + setGetStatus(status, reason); if (! status) { success = false; - std::string reason(status.toString()); - setGetStatus(status, reason); llwarns << "CURL GET FAILED, status: " << status.toHex() << " reason: " << reason << llendl; } @@ -2535,6 +2537,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const worker->setImagePriority(priority); worker->setDesiredDiscard(desired_discard, desired_size); worker->setCanUseHTTP(can_use_http); + worker->setUrl(url); worker->setFakeFailure(fake_failure); if (!worker->haveWork()) { @@ -2741,7 +2744,8 @@ LLTextureFetchWorker* LLTextureFetch::getWorker(const LLUUID& id) // Threads: T* bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, - LLPointer& raw, LLPointer& aux) + LLPointer& raw, LLPointer& aux, + LLCore::HttpStatus& last_http_get_status) { bool res = false; LLTextureFetchWorker* worker = getWorker(id); @@ -2763,6 +2767,7 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, else if (worker->checkWork()) { worker->lockWorkMutex(); // +Mw + last_http_get_status = worker->mGetStatus; discard_level = worker->mDecodedDiscard; raw = worker->mRawImage; aux = worker->mAuxImage; diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index b99480d18e..9f77d58727 100755 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -95,7 +95,8 @@ public: // Threads: T* bool getRequestFinished(const LLUUID& id, S32& discard_level, - LLPointer& raw, LLPointer& aux); + LLPointer& raw, LLPointer& aux, + LLCore::HttpStatus& last_http_get_status); // Threads: T* bool updateRequestPriority(const LLUUID& id, F32 priority); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index a157600cc9..7a1afb1238 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1760,7 +1760,8 @@ bool LLViewerFetchedTexture::updateFetch() if (mRawImage.notNull()) sRawCount--; if (mAuxRawImage.notNull()) sAuxCount--; - bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage); + bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage, + mLastHttpGetStatus); if (mRawImage.notNull()) sRawCount++; if (mAuxRawImage.notNull()) sAuxCount++; if (finished) @@ -1825,14 +1826,25 @@ bool LLViewerFetchedTexture::updateFetch() // We finished but received no data if (current_discard < 0) { - const S32 MAX_FETCH_FAILURE = 1; + const S32 MAX_FETCH_FAILURE = 3; mFetchFailureCount++; - llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount << llendl; - if (getFTType() != FTT_SERVER_BAKE || mFetchFailureCount >= MAX_FETCH_FAILURE) + llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount + << " status " << mLastHttpGetStatus.toHex() << llendl; + // Will retry server-bake textures under a limited set of circumstances. + if (getFTType() == FTT_SERVER_BAKE && + mLastHttpGetStatus.isHttpStatus() && + mLastHttpGetStatus.mType >= 500 && + mLastHttpGetStatus.mType <= 599 && // Only retry 5xx failures. + mFetchFailureCount < MAX_FETCH_FAILURE) + { + llwarns << "Will retry fetch" << llendl; + } + else // Otherwise, assume the image is missing. { llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority << " mRawDiscardLevel " << mRawDiscardLevel << " current_discard " << current_discard + << " stats " << mLastHttpGetStatus.toHex() << llendl; setIsMissingAsset(); desired_discard = -1; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 320e6f8630..91e903ffd6 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -34,6 +34,7 @@ #include "llgltypes.h" #include "llrender.h" #include "llmetricperformancetester.h" +#include "httpcommon.h" #include #include @@ -446,7 +447,8 @@ protected: S8 mIsRawImageValid; S8 mHasFetcher; // We've made a fecth request S8 mIsFetching; // Fetch request is active - bool mCanUseHTTP ; //This texture can be fetched through http if true. + bool mCanUseHTTP; //This texture can be fetched through http if true. + LLCore::HttpStatus mLastHttpGetStatus; // Result of the most recently completed http request for this texture. FTType mFTType; // What category of image is this - map tile, server bake, etc? mutable BOOL mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. -- cgit v1.2.3 From 34e2478388341a1add33bf88cac43031e351340e Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 10 Apr 2013 11:57:22 -0400 Subject: SH-4061 WIP - less log spamming for (expected and normal) map tile failures. --- indra/newview/lltexturefetch.cpp | 21 +++++++++++++++------ indra/newview/llviewertexture.cpp | 20 +++++++++++++------- 2 files changed, 28 insertions(+), 13 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 5a6338d9d8..58cfc80839 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1526,14 +1526,20 @@ bool LLTextureFetchWorker::doWork(S32 param) { if (http_not_found == mGetStatus) { - llwarns << "Texture missing from server (404): " << mUrl << llendl; + if (mFTType != FTT_MAP_TILE) + { + llwarns << "Texture missing from server (404): " << mUrl << llendl; + } - if(mWriteToCacheState == NOT_WRITE) //map tiles + if(mWriteToCacheState == NOT_WRITE) //map tiles or server bakes { setState(DONE); releaseHttpSemaphore(); - LL_WARNS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << llendl; - return true; // failed, means no map tile on the empty region. + if (mFTType != FTT_MAP_TILE) + { + LL_WARNS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << llendl; + } + return true; } @@ -1925,8 +1931,11 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe if (! status) { success = false; - llwarns << "CURL GET FAILED, status: " << status.toHex() - << " reason: " << reason << llendl; + if (mFTType != FTT_MAP_TILE) // missing map tiles are normal, don't complain about them. + { + llwarns << "CURL GET FAILED, status: " << status.toHex() + << " reason: " << reason << llendl; + } } else { diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 7a1afb1238..5f4c66a04c 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1828,8 +1828,11 @@ bool LLViewerFetchedTexture::updateFetch() { const S32 MAX_FETCH_FAILURE = 3; mFetchFailureCount++; - llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount - << " status " << mLastHttpGetStatus.toHex() << llendl; + if (getFTType() != FTT_MAP_TILE) + { + llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount + << " status " << mLastHttpGetStatus.toHex() << llendl; + } // Will retry server-bake textures under a limited set of circumstances. if (getFTType() == FTT_SERVER_BAKE && mLastHttpGetStatus.isHttpStatus() && @@ -1841,11 +1844,14 @@ bool LLViewerFetchedTexture::updateFetch() } else // Otherwise, assume the image is missing. { - llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority - << " mRawDiscardLevel " << mRawDiscardLevel - << " current_discard " << current_discard - << " stats " << mLastHttpGetStatus.toHex() - << llendl; + if (getFTType() != FTT_MAP_TILE) + { + llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority + << " mRawDiscardLevel " << mRawDiscardLevel + << " current_discard " << current_discard + << " stats " << mLastHttpGetStatus.toHex() + << llendl; + } setIsMissingAsset(); desired_discard = -1; } -- cgit v1.2.3 From 2798c355c441f8d92a02537eca6e253c8fbf2bc4 Mon Sep 17 00:00:00 2001 From: "prep@lindenlab.com" Date: Wed, 10 Apr 2013 16:53:46 -0500 Subject: SH-4035:Added ignore message to notification --- indra/newview/llsidepanelappearance.cpp | 6 +----- indra/newview/skins/default/xui/en/notifications.xml | 7 ++++--- 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index ae6ceabdaa..6d2b643434 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -77,13 +77,11 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaBack(const LLSD& notificat S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if ( option == 0 ) { - gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", TRUE); LLAppearanceMgr::instance().setOutfitDirty( true ); showOutfitsInventoryPanel(); LLAppearanceMgr::getInstance()->wearBaseOutfit(); return true; } - gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", FALSE); return false; } @@ -91,13 +89,11 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if ( option == 0 ) - { - gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", TRUE); + { LLAppearanceMgr::getInstance()->wearBaseOutfit(); mLLFloaterSidePanelContainer->close(); return true; } - gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", FALSE); return false; } diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 2170283af2..1ff63c6def 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -10039,9 +10039,10 @@ Cannot create large prims that intersect other players. Please re-try when othe Closing this window will discard any changes you have made. confirm + yestext="OK" + ignoretext="Don't show me this again."/> - + -- cgit v1.2.3 From 14ca6a1247e68805aae22cf573a39819383fe3d4 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 11 Apr 2013 11:18:16 -0400 Subject: SH-4061 WIP - moved retry policy to llmessage, added integration test --- indra/newview/llappearancemgr.cpp | 79 +++------------------------------------ 1 file changed, 5 insertions(+), 74 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index c2be472cbc..85f6f92278 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -52,6 +52,7 @@ #include "llwearablelist.h" #include "llsdutil.h" #include "llsdserialize.h" +#include "llhttpretrypolicy.h" #if LL_MSVC // disable boost::lexical_cast warning @@ -2957,78 +2958,6 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base if (inventory_changed) gInventory.notifyObservers(); } -// This is intended for use with HTTP Clients/Responders, but is not -// specifically coupled with those classes. -class LLHTTPRetryPolicy: public LLThreadSafeRefCount -{ -public: - LLHTTPRetryPolicy() {} - virtual ~LLHTTPRetryPolicy() {} - virtual bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) = 0; -}; - -// Example of simplest possible policy, not necessarily recommended. -// This would be a potentially dangerous policy to enable. Removing for now: -#if 0 -class LLAlwaysRetryImmediatelyPolicy: public LLHTTPRetryPolicy -{ -public: - LLAlwaysRetryImmediatelyPolicy() {} - bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) - { - seconds_to_wait = 0.0; - return true; - } -}; -#endif - -// Very general policy with geometric back-off after failures, -// up to a maximum delay, and maximum number of retries. -class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy -{ -public: - LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries): - mMinDelay(min_delay), - mMaxDelay(max_delay), - mBackoffFactor(backoff_factor), - mMaxRetries(max_retries), - mDelay(min_delay), - mRetryCount(0) - { - } - - bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) - { -#if 0 - // *TODO: Test using status codes to only retry server errors. - // Only server errors would potentially return a different result on retry. - if (!isHttpServerErrorStatus(status)) return false; -#endif - -#if 0 - // *TODO: Honor server Retry-After header. - // Status 503 may ask us to wait for a certain amount of time before retrying. - if (!headers.has(HTTP_IN_HEADER_RETRY_AFTER) - || !getSecondsUntilRetryAfter(headers[HTTP_IN_HEADER_RETRY_AFTER].asStringRef(), seconds_to_wait)) -#endif - { - seconds_to_wait = mDelay; - mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay); - } - - mRetryCount++; - return (mRetryCount<=mMaxRetries); - } - -private: - F32 mMinDelay; // delay never less than this value - F32 mMaxDelay; // delay never exceeds this value - F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay. - U32 mMaxRetries; // maximum number of times shouldRetry will return true. - F32 mDelay; // current delay. - U32 mRetryCount; // number of times shouldRetry has been called. -}; - class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder { LOG_CLASS(RequestAgentUpdateAppearanceResponder); @@ -3084,7 +3013,8 @@ protected: void onFailure() { F32 seconds_to_wait; - if (mRetryPolicy->shouldRetry(getStatus(), getResponseHeaders(), seconds_to_wait)) + mRetryPolicy->onFailure(getStatus(), getResponseHeaders()); + if (mRetryPolicy->shouldRetry(seconds_to_wait)) { llinfos << "retrying" << llendl; doAfterInterval(boost::bind(&LLAppearanceMgr::requestServerAppearanceUpdate, @@ -3327,7 +3257,8 @@ protected: LL_WARNS("Avatar") << "While attempting to increment the agent's cof we got an error " << dumpResponse() << LL_ENDL; F32 seconds_to_wait; - if (mRetryPolicy->shouldRetry(getStatus(), getResponseHeaders(), seconds_to_wait)) + mRetryPolicy->onFailure(getStatus(), getResponseHeaders()); + if (mRetryPolicy->shouldRetry(seconds_to_wait)) { llinfos << "retrying" << llendl; doAfterInterval(boost::bind(&LLAppearanceMgr::incrementCofVersion, -- cgit v1.2.3 From e17920defbf1d39ecd9e88500ba268c59bb84008 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 11 Apr 2013 16:17:23 -0400 Subject: SH-4061 WIP - started adding retry to texture fetch, making retry policy compatible with old and new http libraries --- indra/newview/lltexturefetch.cpp | 1 + indra/newview/lltexturefetch.h | 3 +++ 2 files changed, 4 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 58cfc80839..026f36e205 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1918,6 +1918,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe << " status: " << status.toHex() << " '" << status.toString() << "'" << llendl; + // unsigned int offset(0), length(0), full_length(0); // response->getRange(&offset, &length, &full_length); // llwarns << "HTTP COMPLETE: " << mID << " handle: " << handle diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 9f77d58727..c6bd342a7b 100755 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -396,6 +396,9 @@ private: e_tex_source mFetchSource; e_tex_source mOriginFetchSource; + // Retry logic + LLAdaptiveRetryPolicy mFetchRetryPolicy; + public: //debug use LLTextureFetchDebugger* getFetchDebugger() { return mFetchDebugger;} -- cgit v1.2.3 From a8cdcfc9a893b7debf7c006022b57c389b50bf0d Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 12 Apr 2013 09:16:25 -0400 Subject: SH-4061 WIP - moved retry policy to newview so it can work with either llmessage or CoreHttp libraries. Updated tests. --- indra/newview/CMakeLists.txt | 5 + indra/newview/llhttpretrypolicy.cpp | 117 +++++++++++ indra/newview/llhttpretrypolicy.h | 94 +++++++++ indra/newview/lltexturefetch.h | 2 +- indra/newview/tests/llhttpretrypolicy_test.cpp | 275 +++++++++++++++++++++++++ 5 files changed, 492 insertions(+), 1 deletion(-) mode change 100644 => 100755 indra/newview/CMakeLists.txt create mode 100755 indra/newview/llhttpretrypolicy.cpp create mode 100755 indra/newview/llhttpretrypolicy.h create mode 100755 indra/newview/tests/llhttpretrypolicy_test.cpp (limited to 'indra/newview') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt old mode 100644 new mode 100755 index 05736f6360..27dbe15005 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -299,6 +299,7 @@ set(viewer_SOURCE_FILES llgroupmgr.cpp llhints.cpp llhomelocationresponder.cpp + llhttpretrypolicy.cpp llhudeffect.cpp llhudeffectbeam.cpp llhudeffectlookat.cpp @@ -877,6 +878,7 @@ set(viewer_HEADER_FILES llgrouplist.h llgroupmgr.h llhints.h + llhttpretrypolicy.h llhomelocationresponder.h llhudeffect.h llhudeffectbeam.h @@ -2152,6 +2154,7 @@ if (LL_TESTS) set(test_libs ${LLMESSAGE_LIBRARIES} + ${LLCOREHTTP_LIBRARIES} ${WINDOWS_LIBRARIES} ${LLVFS_LIBRARIES} ${LLMATH_LIBRARIES} @@ -2197,6 +2200,8 @@ if (LL_TESTS) "${test_libs}" ) + LL_ADD_INTEGRATION_TEST(llhttpretrypolicy "llhttpretrypolicy.cpp" "${test_libs}") + #ADD_VIEWER_BUILD_TEST(llmemoryview viewer) #ADD_VIEWER_BUILD_TEST(llagentaccess viewer) #ADD_VIEWER_BUILD_TEST(lltextureinfo viewer) diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp new file mode 100755 index 0000000000..5c6dabbe99 --- /dev/null +++ b/indra/newview/llhttpretrypolicy.cpp @@ -0,0 +1,117 @@ +/** + * @file llhttpretrypolicy.h + * @brief Header for a retry policy class intended for use with http responders. + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llhttpretrypolicy.h" + +bool LLAdaptiveRetryPolicy::getRetryAfter(const LLSD& headers, F32& retry_header_time) +{ + return (headers.has(HTTP_IN_HEADER_RETRY_AFTER) + && getSecondsUntilRetryAfter(headers[HTTP_IN_HEADER_RETRY_AFTER].asStringRef(), retry_header_time)); +} + +bool LLAdaptiveRetryPolicy::getRetryAfter(const LLCore::HttpHeaders *headers, F32& retry_header_time) +{ + // Look for matching header. Hopefully it's correct enough to let + // us extract the field we are looking for. Does not purport to be + // in any way a viable general HTTP header parser. + if (headers) + { + for (std::vector::const_iterator it = headers->mHeaders.begin(); + it != headers->mHeaders.end(); + ++it) + { + const std::string& str = *it; + const std::string match = HTTP_IN_HEADER_RETRY_AFTER + ":"; + size_t pos = str.find(match); + if ((pos != std::string::npos) && + (pos+match.length() <= str.length())) + { + retry_header_time = strtod(str.substr(pos+match.length()).c_str(), NULL); + return true; + } + } + } + return false; +} + +void LLAdaptiveRetryPolicy::onFailure(S32 status, const LLSD& headers) +{ + F32 retry_header_time; + bool has_retry_header_time = getRetryAfter(headers,retry_header_time); + onFailureCommon(status, has_retry_header_time, retry_header_time); +} + +// TODO: replace this parsing junk once CoreHttp has its own header parsing capabilities. +void LLAdaptiveRetryPolicy::onFailure(const LLCore::HttpResponse *response) +{ + F32 retry_header_time; + const LLCore::HttpHeaders *headers = response->getHeaders(); + bool has_retry_header_time = getRetryAfter(headers,retry_header_time); + onFailureCommon(response->getStatus().mType, has_retry_header_time, retry_header_time); +} + +void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time) +{ + if (mRetryCount > 0) + { + mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay); + } + // Honor server Retry-After header. + // Status 503 may ask us to wait for a certain amount of time before retrying. + F32 wait_time = mDelay; + if (has_retry_header_time) + { + wait_time = retry_header_time; + } + + if (mRetryCount>=mMaxRetries) + { + llinfos << "Too many retries " << mRetryCount << ", will not retry" << llendl; + mShouldRetry = false; + } + if (!isHttpServerErrorStatus(status)) + { + llinfos << "Non-server error " << status << ", will not retry" << llendl; + mShouldRetry = false; + } + if (mShouldRetry) + { + llinfos << "Retry count " << mRetryCount << " should retry after " << wait_time << llendl; + mRetryTimer.reset(); + mRetryTimer.setTimerExpirySec(wait_time); + } + mRetryCount++; +} + + +bool LLAdaptiveRetryPolicy::shouldRetry(F32& seconds_to_wait) const +{ + llassert(mRetryCount>0); // have to call onFailure() before shouldRetry() + seconds_to_wait = mShouldRetry ? mRetryTimer.getRemainingTimeF32() : F32_MAX; + return mShouldRetry; +} diff --git a/indra/newview/llhttpretrypolicy.h b/indra/newview/llhttpretrypolicy.h new file mode 100755 index 0000000000..ca37e5f73c --- /dev/null +++ b/indra/newview/llhttpretrypolicy.h @@ -0,0 +1,94 @@ +/** + * @file file llhttpretrypolicy.h + * @brief declarations for http retry policy class. + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_RETRYPOLICY_H +#define LL_RETRYPOLICY_H + +#include "lltimer.h" +#include "llthread.h" + +#include "llhttpconstants.h" + +// For compatibility with new core http lib. +#include "httpresponse.h" +#include "httpheaders.h" + +// This is intended for use with HTTP Clients/Responders, but is not +// specifically coupled with those classes. +class LLHTTPRetryPolicy: public LLThreadSafeRefCount +{ +public: + LLHTTPRetryPolicy() {} + virtual ~LLHTTPRetryPolicy() {} + // Call once after an HTTP failure to update state. + virtual void onFailure(S32 status, const LLSD& headers) = 0; + + virtual void onFailure(const LLCore::HttpResponse *response) = 0; + + virtual bool shouldRetry(F32& seconds_to_wait) const = 0; +}; + +// Very general policy with geometric back-off after failures, +// up to a maximum delay, and maximum number of retries. +class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy +{ +public: + LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries): + mMinDelay(min_delay), + mMaxDelay(max_delay), + mBackoffFactor(backoff_factor), + mMaxRetries(max_retries), + mDelay(min_delay), + mRetryCount(0), + mShouldRetry(true) + { + } + + // virtual + void onFailure(S32 status, const LLSD& headers); + // virtual + void onFailure(const LLCore::HttpResponse *response); + // virtual + bool shouldRetry(F32& seconds_to_wait) const; + +protected: + bool getRetryAfter(const LLSD& headers, F32& retry_header_time); + bool getRetryAfter(const LLCore::HttpHeaders *headers, F32& retry_header_time); + void onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time); + +private: + + F32 mMinDelay; // delay never less than this value + F32 mMaxDelay; // delay never exceeds this value + F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay. + U32 mMaxRetries; // maximum number of times shouldRetry will return true. + F32 mDelay; // current default delay. + U32 mRetryCount; // number of times shouldRetry has been called. + LLTimer mRetryTimer; // time until next retry. + bool mShouldRetry; // Becomes false after too many retries, or the wrong sort of status received, etc. +}; + +#endif diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index c6bd342a7b..12226d51c8 100755 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -397,7 +397,7 @@ private: e_tex_source mOriginFetchSource; // Retry logic - LLAdaptiveRetryPolicy mFetchRetryPolicy; + //LLAdaptiveRetryPolicy mFetchRetryPolicy; public: //debug use diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp new file mode 100755 index 0000000000..39bd15d62f --- /dev/null +++ b/indra/newview/tests/llhttpretrypolicy_test.cpp @@ -0,0 +1,275 @@ +/** + * @file llhttpretrypolicy_test.cpp + * @brief Header tests to exercise the LLHTTPRetryPolicy classes. + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "../llviewerprecompiledheaders.h" +#include "../llhttpretrypolicy.h" +#include "lltut.h" + +namespace tut +{ +struct TestData +{ +}; + +typedef test_group RetryPolicyTestGroup; +typedef RetryPolicyTestGroup::object RetryPolicyTestObject; +RetryPolicyTestGroup retryPolicyTestGroup("retry_policy"); + +template<> template<> +void RetryPolicyTestObject::test<1>() +{ + LLAdaptiveRetryPolicy never_retry(1.0,1.0,1.0,0); + LLSD headers; + F32 wait_seconds; + + never_retry.onFailure(500,headers); + ensure("never retry", !never_retry.shouldRetry(wait_seconds)); +} + +template<> template<> +void RetryPolicyTestObject::test<2>() +{ + LLAdaptiveRetryPolicy retry404(1.0,2.0,3.0,10); + LLSD headers; + F32 wait_seconds; + + retry404.onFailure(404,headers); + ensure("no retry on 404", !retry404.shouldRetry(wait_seconds)); +} + +template<> template<> +void RetryPolicyTestObject::test<3>() +{ + // Should retry after 1.0, 2.0, 3.0, 3.0 seconds. + LLAdaptiveRetryPolicy basic_retry(1.0,3.0,2.0,4); + LLSD headers; + F32 wait_seconds; + bool should_retry; + U32 frac_bits = 6; + + // Starting wait 1.0 + basic_retry.onFailure(500,headers); + should_retry = basic_retry.shouldRetry(wait_seconds); + ensure("basic_retry 1", should_retry); + ensure_approximately_equals("basic_retry 1", wait_seconds, 1.0F, frac_bits); + + // Double wait to 2.0 + basic_retry.onFailure(500,headers); + should_retry = basic_retry.shouldRetry(wait_seconds); + ensure("basic_retry 2", should_retry); + ensure_approximately_equals("basic_retry 2", wait_seconds, 2.0F, frac_bits); + + // Hit max wait of 3.0 (4.0 clamped to max 3) + basic_retry.onFailure(500,headers); + should_retry = basic_retry.shouldRetry(wait_seconds); + ensure("basic_retry 3", should_retry); + ensure_approximately_equals("basic_retry 3", wait_seconds, 3.0F, frac_bits); + + // At max wait, should stay at 3.0 + basic_retry.onFailure(500,headers); + should_retry = basic_retry.shouldRetry(wait_seconds); + ensure("basic_retry 4", should_retry); + ensure_approximately_equals("basic_retry 4", wait_seconds, 3.0F, frac_bits); + + // Max retries, should fail now. + basic_retry.onFailure(500,headers); + should_retry = basic_retry.shouldRetry(wait_seconds); + ensure("basic_retry 5", !should_retry); +} + +// Retries should stop as soon as a non-5xx error is received. +template<> template<> +void RetryPolicyTestObject::test<4>() +{ + // Should retry after 1.0, 2.0, 3.0, 3.0 seconds. + LLAdaptiveRetryPolicy killer404(1.0,3.0,2.0,4); + LLSD headers; + F32 wait_seconds; + bool should_retry; + U32 frac_bits = 6; + + // Starting wait 1.0 + killer404.onFailure(500,headers); + should_retry = killer404.shouldRetry(wait_seconds); + ensure("killer404 1", should_retry); + ensure_approximately_equals("killer404 1", wait_seconds, 1.0F, frac_bits); + + // Double wait to 2.0 + killer404.onFailure(500,headers); + should_retry = killer404.shouldRetry(wait_seconds); + ensure("killer404 2", should_retry); + ensure_approximately_equals("killer404 2", wait_seconds, 2.0F, frac_bits); + + // Should fail on non-5xx + killer404.onFailure(404,headers); + should_retry = killer404.shouldRetry(wait_seconds); + ensure("killer404 3", !should_retry); + + // After a non-5xx, should keep failing. + killer404.onFailure(500,headers); + should_retry = killer404.shouldRetry(wait_seconds); + ensure("killer404 4", !should_retry); +} + +// Test handling of "retry-after" header. If present, this header +// value overrides the computed delay, but does not affect the +// progression of delay values. For example, if the normal +// progression of delays would be 1,2,4,8..., but the 2nd and 3rd calls +// get a retry header of 33, the pattern would become 1,33,33,8... +template<> template<> +void RetryPolicyTestObject::test<5>() +{ + LLAdaptiveRetryPolicy policy(1.0,25.0,2.0,6); + LLSD headers_with_retry; + headers_with_retry[HTTP_IN_HEADER_RETRY_AFTER] = "666"; + LLSD headers_without_retry; + F32 wait_seconds; + bool should_retry; + U32 frac_bits = 6; + + policy.onFailure(500,headers_without_retry); + should_retry = policy.shouldRetry(wait_seconds); + ensure("retry header 1", should_retry); + ensure_approximately_equals("retry header 1", wait_seconds, 1.0F, frac_bits); + + policy.onFailure(500,headers_without_retry); + should_retry = policy.shouldRetry(wait_seconds); + ensure("retry header 2", should_retry); + ensure_approximately_equals("retry header 2", wait_seconds, 2.0F, frac_bits); + + policy.onFailure(500,headers_with_retry); + should_retry = policy.shouldRetry(wait_seconds); + ensure("retry header 3", should_retry); + // 4.0 overrides by header -> 666.0 + ensure_approximately_equals("retry header 3", wait_seconds, 666.0F, frac_bits); + + policy.onFailure(500,headers_with_retry); + should_retry = policy.shouldRetry(wait_seconds); + ensure("retry header 4", should_retry); + // 8.0 overrides by header -> 666.0 + ensure_approximately_equals("retry header 4", wait_seconds, 666.0F, frac_bits); + + policy.onFailure(500,headers_without_retry); + should_retry = policy.shouldRetry(wait_seconds); + ensure("retry header 5", should_retry); + ensure_approximately_equals("retry header 5", wait_seconds, 16.0F, frac_bits); + + policy.onFailure(500,headers_without_retry); + should_retry = policy.shouldRetry(wait_seconds); + ensure("retry header 6", should_retry); + ensure_approximately_equals("retry header 6", wait_seconds, 25.0F, frac_bits); + + policy.onFailure(500,headers_with_retry); + should_retry = policy.shouldRetry(wait_seconds); + ensure("retry header 7", !should_retry); +} + +// Test getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait), +// used by header parsing of the retry policy. +template<> template<> +void RetryPolicyTestObject::test<6>() +{ + F32 seconds_to_wait; + bool success; + + std::string str1("0"); + seconds_to_wait = F32_MAX; + success = getSecondsUntilRetryAfter(str1, seconds_to_wait); + ensure("parse 1", success); + ensure_equals("parse 1", seconds_to_wait, 0.0); + + std::string str2("999.9"); + seconds_to_wait = F32_MAX; + success = getSecondsUntilRetryAfter(str2, seconds_to_wait); + ensure("parse 2", success); + ensure_approximately_equals("parse 2", seconds_to_wait, 999.9F, 8); + + time_t nowseconds; + time(&nowseconds); + std::string str3 = LLDate((F64)nowseconds).asRFC1123(); + seconds_to_wait = F32_MAX; + success = getSecondsUntilRetryAfter(str3, seconds_to_wait); + ensure("parse 3", success); + ensure_approximately_equals("parse 3", seconds_to_wait, 0.0F, 6); +} + +// Test retry-after field in both llmessage and CoreHttp headers. +template<> template<> +void RetryPolicyTestObject::test<7>() +{ + LLSD sd_headers; + time_t nowseconds; + time(&nowseconds); + sd_headers[HTTP_IN_HEADER_RETRY_AFTER] = LLDate((F64)nowseconds).asRFC1123(); + LLAdaptiveRetryPolicy policy(17.0,644.0,3.0,10); + F32 seconds_to_wait; + bool should_retry; + + // no retry header, use default. + policy.onFailure(500,LLSD()); + should_retry = policy.shouldRetry(seconds_to_wait); + ensure("header 1", should_retry); + ensure_approximately_equals("header 1", seconds_to_wait, 17.0F, 6); + + // retry header should override, give delay of 0 + policy.onFailure(503,sd_headers); + should_retry = policy.shouldRetry(seconds_to_wait); + ensure("header 2", should_retry); + ensure_approximately_equals("header 2", seconds_to_wait, 0.0F, 6); + + // retry header in LLCore::HttpHeaders + { + LLCore::HttpResponse *response = new LLCore::HttpResponse(); + LLCore::HttpHeaders *headers = new LLCore::HttpHeaders(); + response->setStatus(503); + response->setHeaders(headers); + headers->mHeaders.push_back("retry-after: 600"); + policy.onFailure(response); + should_retry = policy.shouldRetry(seconds_to_wait); + ensure("header 3",should_retry); + ensure_approximately_equals("header 3", seconds_to_wait, 600.0F, 6); + response->release(); + } + + // retry header in LLCore::HttpHeaders + { + LLCore::HttpResponse *response = new LLCore::HttpResponse(); + LLCore::HttpHeaders *headers = new LLCore::HttpHeaders(); + response->setStatus(503); + response->setHeaders(headers); + LLSD sd_headers; + time(&nowseconds); + headers->mHeaders.push_back("retry-after: " + LLDate((F64)nowseconds).asRFC1123()); + policy.onFailure(response); + should_retry = policy.shouldRetry(seconds_to_wait); + ensure("header 3",should_retry); + ensure_approximately_equals("header 3", seconds_to_wait, 0.0F, 6); + response->release(); + } +} + +} + -- cgit v1.2.3 From 766daa73a29d34cb3410c033fc99bfc156844c92 Mon Sep 17 00:00:00 2001 From: "prep@lindenlab.com" Date: Fri, 12 Apr 2013 10:09:44 -0500 Subject: Sh-4035: Fix for skin changes not being reverted after cancel --- indra/newview/llsidepanelappearance.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/newview') diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 6d2b643434..7b89e0617b 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -90,6 +90,7 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if ( option == 0 ) { + mEditWearable->revertChanges(); LLAppearanceMgr::getInstance()->wearBaseOutfit(); mLLFloaterSidePanelContainer->close(); return true; -- cgit v1.2.3 From bb237ce15f0a7bc4a3fbffc45b1e4548fd1d2f81 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 12 Apr 2013 17:04:48 -0400 Subject: SH_4061 WIP - retry policy org and tests --- indra/newview/llhttpretrypolicy.cpp | 23 +++++++++++++++++- indra/newview/llhttpretrypolicy.h | 11 +-------- indra/newview/tests/llhttpretrypolicy_test.cpp | 33 +++++++++++++++++++++----- 3 files changed, 50 insertions(+), 17 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp index 5c6dabbe99..82f6eab00e 100755 --- a/indra/newview/llhttpretrypolicy.cpp +++ b/indra/newview/llhttpretrypolicy.cpp @@ -28,6 +28,17 @@ #include "llhttpretrypolicy.h" +LLAdaptiveRetryPolicy::LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries): + mMinDelay(min_delay), + mMaxDelay(max_delay), + mBackoffFactor(backoff_factor), + mMaxRetries(max_retries), + mDelay(min_delay), + mRetryCount(0), + mShouldRetry(true) +{ +} + bool LLAdaptiveRetryPolicy::getRetryAfter(const LLSD& headers, F32& retry_header_time) { return (headers.has(HTTP_IN_HEADER_RETRY_AFTER) @@ -77,6 +88,11 @@ void LLAdaptiveRetryPolicy::onFailure(const LLCore::HttpResponse *response) void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time) { + if (!mShouldRetry) + { + llinfos << "keep on failing" << llendl; + return; + } if (mRetryCount > 0) { mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay); @@ -111,7 +127,12 @@ void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_ti bool LLAdaptiveRetryPolicy::shouldRetry(F32& seconds_to_wait) const { - llassert(mRetryCount>0); // have to call onFailure() before shouldRetry() + if (mRetryCount == 0) + { + // Called shouldRetry before any failure. + seconds_to_wait = F32_MAX; + return false; + } seconds_to_wait = mShouldRetry ? mRetryTimer.getRemainingTimeF32() : F32_MAX; return mShouldRetry; } diff --git a/indra/newview/llhttpretrypolicy.h b/indra/newview/llhttpretrypolicy.h index ca37e5f73c..6f63f047de 100755 --- a/indra/newview/llhttpretrypolicy.h +++ b/indra/newview/llhttpretrypolicy.h @@ -56,16 +56,7 @@ public: class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy { public: - LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries): - mMinDelay(min_delay), - mMaxDelay(max_delay), - mBackoffFactor(backoff_factor), - mMaxRetries(max_retries), - mDelay(min_delay), - mRetryCount(0), - mShouldRetry(true) - { - } + LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries); // virtual void onFailure(S32 status, const LLSD& headers); diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp index 39bd15d62f..43fc1178cc 100755 --- a/indra/newview/tests/llhttpretrypolicy_test.cpp +++ b/indra/newview/tests/llhttpretrypolicy_test.cpp @@ -45,8 +45,12 @@ void RetryPolicyTestObject::test<1>() LLSD headers; F32 wait_seconds; + // No retry until we've finished a try. + ensure("never retry 0", !never_retry.shouldRetry(wait_seconds)); + + // 0 retries max. never_retry.onFailure(500,headers); - ensure("never retry", !never_retry.shouldRetry(wait_seconds)); + ensure("never retry 1", !never_retry.shouldRetry(wait_seconds)); } template<> template<> @@ -70,6 +74,9 @@ void RetryPolicyTestObject::test<3>() bool should_retry; U32 frac_bits = 6; + // No retry until we've finished a try. + ensure("basic_retry 0", !basic_retry.shouldRetry(wait_seconds)); + // Starting wait 1.0 basic_retry.onFailure(500,headers); should_retry = basic_retry.shouldRetry(wait_seconds); @@ -224,10 +231,13 @@ void RetryPolicyTestObject::test<7>() time_t nowseconds; time(&nowseconds); sd_headers[HTTP_IN_HEADER_RETRY_AFTER] = LLDate((F64)nowseconds).asRFC1123(); - LLAdaptiveRetryPolicy policy(17.0,644.0,3.0,10); + LLAdaptiveRetryPolicy policy(17.0,644.0,3.0,5); F32 seconds_to_wait; bool should_retry; + // No retry until we've finished a try. + ensure("header 0", !policy.shouldRetry(seconds_to_wait)); + // no retry header, use default. policy.onFailure(500,LLSD()); should_retry = policy.shouldRetry(seconds_to_wait); @@ -246,7 +256,7 @@ void RetryPolicyTestObject::test<7>() LLCore::HttpHeaders *headers = new LLCore::HttpHeaders(); response->setStatus(503); response->setHeaders(headers); - headers->mHeaders.push_back("retry-after: 600"); + headers->mHeaders.push_back(HTTP_IN_HEADER_RETRY_AFTER + ": 600"); policy.onFailure(response); should_retry = policy.shouldRetry(seconds_to_wait); ensure("header 3",should_retry); @@ -262,13 +272,24 @@ void RetryPolicyTestObject::test<7>() response->setHeaders(headers); LLSD sd_headers; time(&nowseconds); - headers->mHeaders.push_back("retry-after: " + LLDate((F64)nowseconds).asRFC1123()); + headers->mHeaders.push_back(HTTP_IN_HEADER_RETRY_AFTER + ": " + LLDate((F64)nowseconds).asRFC1123()); policy.onFailure(response); should_retry = policy.shouldRetry(seconds_to_wait); - ensure("header 3",should_retry); - ensure_approximately_equals("header 3", seconds_to_wait, 0.0F, 6); + ensure("header 4",should_retry); + ensure_approximately_equals("header 4", seconds_to_wait, 0.0F, 6); response->release(); } + + // Timeout should be clamped at max. + policy.onFailure(500,LLSD()); + should_retry = policy.shouldRetry(seconds_to_wait); + ensure("header 5", should_retry); + ensure_approximately_equals("header 5", seconds_to_wait, 644.0F, 6); + + // No more retries. + policy.onFailure(500,LLSD()); + should_retry = policy.shouldRetry(seconds_to_wait); + ensure("header 6", !should_retry); } } -- cgit v1.2.3 From 8868964b549822f260694c2bf26b903dbce8ed0a Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Mon, 15 Apr 2013 16:55:35 +0000 Subject: SH-4106 Significantly upgrade the HttpHeaders interface for SSB. Header container moves from a vector of raw lines to a vector of string pairs representing name/value pairs in headers. For incoming headers, we normalize the name to lowercase and trim it. Values are only left-trimmed. Outgoing headers are left as-is. Simple find() method for the common case, forward and reverse iterators for those few who need to do it themselves. The HTTP status line (e.g. 'HTTP/1.1 200 Ok') is no longer treated as a header to be returned to caller. Unit tests, as usual, were a bear but they absolutely ensured outgoing HTTP header conformance after the change. Grunt work paid off. LLTextureFetch was also given a second options structure for texture fetches. Same as the original but with header return to caller requested. Baked textures should use this, the other 20,000 texture fetch requests should continue to use the original. --- indra/newview/lltexturefetch.cpp | 17 +++++++++++++---- indra/newview/lltexturefetch.h | 3 ++- 2 files changed, 15 insertions(+), 5 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index cc6dc64626..5e12c341d5 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. + * Copyright (C) 2012-2013, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -2376,6 +2376,7 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mQAMode(qa_mode), mHttpRequest(NULL), mHttpOptions(NULL), + mHttpOptionsWithHeaders(NULL), mHttpHeaders(NULL), mHttpMetricsHeaders(NULL), mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID), @@ -2406,11 +2407,13 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mHttpRequest = new LLCore::HttpRequest; mHttpOptions = new LLCore::HttpOptions; + mHttpOptionsWithHeaders = new LLCore::HttpOptions; + mHttpOptionsWithHeaders->setWantHeaders(true); mHttpHeaders = new LLCore::HttpHeaders; // *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ? - mHttpHeaders->mHeaders.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C); + mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_IMAGE_X_J2C); mHttpMetricsHeaders = new LLCore::HttpHeaders; - mHttpMetricsHeaders->mHeaders.push_back(HTTP_OUT_HEADER_CONTENT_TYPE + ": " + HTTP_CONTENT_LLSD_XML); + mHttpMetricsHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML); mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicyDefault(); } @@ -2431,6 +2434,12 @@ LLTextureFetch::~LLTextureFetch() mHttpOptions = NULL; } + if (mHttpOptionsWithHeaders) + { + mHttpOptionsWithHeaders->release(); + mHttpOptionsWithHeaders = NULL; + } + if (mHttpHeaders) { mHttpHeaders->release(); @@ -4043,7 +4052,7 @@ void LLTextureFetchDebugger::init() { mHttpHeaders = new LLCore::HttpHeaders; // *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ? - mHttpHeaders->mHeaders.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C); + mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_IMAGE_X_J2C); } } diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 902a3d7a25..3c79a5a24d 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. + * Copyright (C) 2012-2013, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -351,6 +351,7 @@ private: // LLCurl interfaces used in the past. LLCore::HttpRequest * mHttpRequest; // Ttf LLCore::HttpOptions * mHttpOptions; // Ttf + LLCore::HttpOptions * mHttpOptionsWithHeaders; // Ttf LLCore::HttpHeaders * mHttpHeaders; // Ttf LLCore::HttpHeaders * mHttpMetricsHeaders; // Ttf LLCore::HttpRequest::policy_t mHttpPolicyClass; // T* -- cgit v1.2.3 From 5976dc144e774ae363cbf774337ccf663015cc6d Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 15 Apr 2013 15:12:22 -0400 Subject: SH-4061 WIP - simulated failures/image fetch retries --- indra/newview/lltexturefetch.cpp | 113 ++++++++++++++++++++++++++++++-------- indra/newview/llviewertexture.cpp | 2 +- indra/newview/llvoavatar.cpp | 2 +- 3 files changed, 92 insertions(+), 25 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 026f36e205..8e78638c0a 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -63,6 +63,8 @@ #include "bufferarray.h" #include "bufferstream.h" +#include "llhttpretrypolicy.h" + bool LLTextureFetchDebugger::sDebuggerEnabled = false ; LLStat LLTextureFetch::sCacheHitRate("texture_cache_hits", 128); LLStat LLTextureFetch::sCacheReadLatency("texture_cache_read_latency", 128); @@ -244,6 +246,25 @@ static const S32 HTTP_REQUESTS_IN_QUEUE_LOW_WATER = 20; // Active level at whi ////////////////////////////////////////////////////////////////////////////// +static const char* e_state_name[] = +{ + "INVALID", + "INIT", + "LOAD_FROM_TEXTURE_CACHE", + "CACHE_POST", + "LOAD_FROM_NETWORK", + "LOAD_FROM_SIMULATOR", + "WAIT_HTTP_RESOURCE", + "WAIT_HTTP_RESOURCE2", + "SEND_HTTP_REQ", + "WAIT_HTTP_REQ", + "DECODE_IMAGE", + "DECODE_IMAGE_UPDATE", + "WRITE_TO_CACHE", + "WAIT_ON_WRITE", + "DONE" +}; + class LLTextureFetchWorker : public LLWorkerClass, public LLCore::HttpHandler { @@ -552,6 +573,8 @@ private: LLCore::HttpStatus mGetStatus; std::string mGetReason; bool mFakeFailure; + LLAdaptiveRetryPolicy mFetchRetryPolicy; + // Work Data LLMutex mWorkMutex; @@ -896,7 +919,8 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mCacheReadCount(0U), mCacheWriteCount(0U), mResourceWaitCount(0U), - mFakeFailure(fake_failure) + mFakeFailure(fake_failure), + mFetchRetryPolicy(15.0,15.0,1.0,10) { mCanUseNET = mUrl.empty() ; @@ -1277,6 +1301,20 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == LOAD_FROM_NETWORK) { + // Check for retries to previous server failures. + F32 wait_seconds; + if (mFetchRetryPolicy.shouldRetry(wait_seconds)) + { + if (wait_seconds <= 0.0) + { + llinfos << mID << " retrying now" << llendl; + } + else + { + //llinfos << mID << " waiting to retry for " << wait_seconds << " seconds" << llendl; + return false; + } + } static LLCachedControl use_http(gSavedSettings,"ImagePipelineUseHTTP"); // if (mHost != LLHost::invalid) get_url = false; @@ -1557,6 +1595,10 @@ bool LLTextureFetchWorker::doWork(S32 param) else if (http_service_unavail == mGetStatus) { LL_INFOS_ONCE("Texture") << "Texture server busy (503): " << mUrl << LL_ENDL; + llinfos << "503: HTTP GET failed for: " << mUrl + << " Status: " << mGetStatus.toHex() + << " Reason: '" << mGetReason << "'" + << llendl; } else if (http_not_sat == mGetStatus) { @@ -1565,11 +1607,29 @@ bool LLTextureFetchWorker::doWork(S32 param) } else { - llinfos << "HTTP GET failed for: " << mUrl + llinfos << "other: HTTP GET failed for: " << mUrl << " Status: " << mGetStatus.toHex() << " Reason: '" << mGetReason << "'" << llendl; } +#if 0 + if (isHttpServerErrorStatus(mGetStatus.mType)) + { + // Check for retry + F32 wait_seconds; + if (mFetchRetryPolicy.shouldRetry(wait_seconds)) + { + llinfos << mID << " status " << (S32) mGetStatus.mType << " will retry after " << wait_seconds << llendl; + setState(INIT); + releaseHttpSemaphore(); + return false; + } + else + { + llinfos << mID << " will not retry on status " << (S32) mGetStatus.mType << llendl; + } + } +#endif mUrl.clear(); if (cur_size > 0) @@ -1907,12 +1967,33 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe if (mFakeFailure) { - llwarns << "For debugging, setting fake failure status for texture " << mID << llendl; + llwarns << mID << " for debugging, setting fake failure status for texture " << mID << llendl; response->setStatus(LLCore::HttpStatus(500)); + setFakeFailure(false); } bool success = true; bool partial = false; LLCore::HttpStatus status(response->getStatus()); + if (!status && (mFTType == FTT_SERVER_BAKE)) + { + llinfos << mID << " state " << e_state_name[mState] << llendl; + mFetchRetryPolicy.onFailure(response); + F32 retry_after; + if (mFetchRetryPolicy.shouldRetry(retry_after)) + { + llinfos << mID << " should retry after " << retry_after << ", resetting state to INIT" << llendl; + mFetcher->removeFromHTTPQueue(mID, 0); + std::string reason(status.toString()); + setGetStatus(status, reason); + releaseHttpSemaphore(); + setState(INIT); + return; + } + else + { + llinfos << mID << " should not retry" << llendl; + } + } LL_DEBUGS("Texture") << "HTTP COMPLETE: " << mID << " status: " << status.toHex() @@ -1934,7 +2015,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe success = false; if (mFTType != FTT_MAP_TILE) // missing map tiles are normal, don't complain about them. { - llwarns << "CURL GET FAILED, status: " << status.toHex() + llwarns << mID << " CURL GET FAILED, status: " << status.toHex() << " reason: " << reason << llendl; } } @@ -2488,7 +2569,11 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const { return false; } - + + if (f_type == FTT_SERVER_BAKE) + { + llinfos << " requesting " << id << " " << w << "x" << h << " discard " << desired_discard << llendl; + } LLTextureFetchWorker* worker = getWorker(id) ; if (worker) { @@ -3248,24 +3333,6 @@ bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size) void LLTextureFetchWorker::setState(e_state new_state) { - static const char* e_state_name[] = - { - "INVALID", - "INIT", - "LOAD_FROM_TEXTURE_CACHE", - "CACHE_POST", - "LOAD_FROM_NETWORK", - "LOAD_FROM_SIMULATOR", - "WAIT_HTTP_RESOURCE", - "WAIT_HTTP_RESOURCE2", - "SEND_HTTP_REQ", - "WAIT_HTTP_REQ", - "DECODE_IMAGE", - "DECODE_IMAGE_UPDATE", - "WRITE_TO_CACHE", - "WAIT_ON_WRITE", - "DONE" - }; LL_DEBUGS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl; mState = new_state; } diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 5f4c66a04c..8f7c8e40b7 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1826,7 +1826,7 @@ bool LLViewerFetchedTexture::updateFetch() // We finished but received no data if (current_discard < 0) { - const S32 MAX_FETCH_FAILURE = 3; + const S32 MAX_FETCH_FAILURE = 1; mFetchFailureCount++; if (getFTType() != FTT_MAP_TILE) { diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index cf4cc64ac3..a2ba8f36aa 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -7302,7 +7302,7 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 ); if (id == image_baked->getID()) { - LL_DEBUGS("Avatar") << avString() << " i " << i << " id " << id << LL_ENDL; + //LL_DEBUGS("Avatar") << avString() << " i " << i << " id " << id << LL_ENDL; mBakedTextureDatas[i].mIsLoaded = true; mBakedTextureDatas[i].mLastTextureID = id; mBakedTextureDatas[i].mIsUsed = true; -- cgit v1.2.3 From 7182203ebf4ba914c3a49f9593b1ed831fa6c1e9 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 15 Apr 2013 17:46:28 -0400 Subject: SH-4061 WIP - moved all retry logic into lltexturefetch, some cleanup. Debug setting now defines a fake failure rate. --- indra/newview/app_settings/logcontrol.xml | 0 indra/newview/app_settings/settings.xml | 6 ++--- indra/newview/lltexturefetch.cpp | 37 +++++++++++++------------ indra/newview/lltexturefetch.h | 2 +- indra/newview/llviewertexture.cpp | 45 +++++++------------------------ indra/newview/llviewertexture.h | 1 - 6 files changed, 33 insertions(+), 58 deletions(-) mode change 100644 => 100755 indra/newview/app_settings/logcontrol.xml (limited to 'indra/newview') diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml old mode 100644 new mode 100755 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 0b7f99ebc1..18a33b3542 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11130,16 +11130,16 @@ Value 0 - TextureFetchFakeFailures + TextureFetchFakeFailureRate Comment Simulate HTTP fetch failures for some server bake textures. Persist 1 Type - Boolean + F32 Value - 0 + 0.0 TextureFetchSource diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 8e78638c0a..2cebd4b6eb 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -410,13 +410,11 @@ public: // Inherited from LLCore::HttpHandler // Threads: Ttf virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); - - void setFakeFailure(bool fake_failure) { mFakeFailure = fake_failure; } protected: LLTextureFetchWorker(LLTextureFetch* fetcher, FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, - F32 priority, S32 discard, S32 size, bool fake_failure); + F32 priority, S32 discard, S32 size); private: @@ -572,7 +570,6 @@ private: S32 mActiveCount; LLCore::HttpStatus mGetStatus; std::string mGetReason; - bool mFakeFailure; LLAdaptiveRetryPolicy mFetchRetryPolicy; @@ -864,8 +861,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, const LLHost& host, // Simulator host F32 priority, // Priority S32 discard, // Desired discard - S32 size, // Desired size - bool fake_failure) // For testing, simulate http failure if true. + S32 size) // Desired size : LLWorkerClass(fetcher, "TextureFetch"), LLCore::HttpHandler(), mState(INIT), @@ -919,7 +915,6 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mCacheReadCount(0U), mCacheWriteCount(0U), mResourceWaitCount(0U), - mFakeFailure(fake_failure), mFetchRetryPolicy(15.0,15.0,1.0,10) { mCanUseNET = mUrl.empty() ; @@ -1179,6 +1174,7 @@ bool LLTextureFetchWorker::doWork(S32 param) mDesiredSize = llmax(mDesiredSize, TEXTURE_CACHE_ENTRY_SIZE); // min desired size is TEXTURE_CACHE_ENTRY_SIZE LL_DEBUGS("Texture") << mID << ": Priority: " << llformat("%8.0f",mImagePriority) << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; + // fall through } @@ -1315,6 +1311,7 @@ bool LLTextureFetchWorker::doWork(S32 param) return false; } } + static LLCachedControl use_http(gSavedSettings,"ImagePipelineUseHTTP"); // if (mHost != LLHost::invalid) get_url = false; @@ -1965,11 +1962,14 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow); } - if (mFakeFailure) + static LLCachedControl fake_failure_rate(gSavedSettings, "TextureFetchFakeFailureRate"); + F32 rand_val = ll_frand(); + F32 rate = fake_failure_rate; + if (mFTType == FTT_SERVER_BAKE && (fake_failure_rate > 0.0) && (rand_val < fake_failure_rate)) { - llwarns << mID << " for debugging, setting fake failure status for texture " << mID << llendl; - response->setStatus(LLCore::HttpStatus(500)); - setFakeFailure(false); + llwarns << mID << " for debugging, setting fake failure status for texture " << mID + << " (rand was " << rand_val << "/" << rate << ")" << llendl; + response->setStatus(LLCore::HttpStatus(503)); } bool success = true; bool partial = false; @@ -1981,12 +1981,12 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe F32 retry_after; if (mFetchRetryPolicy.shouldRetry(retry_after)) { - llinfos << mID << " should retry after " << retry_after << ", resetting state to INIT" << llendl; + llinfos << mID << " should retry after " << retry_after << ", resetting state to LOAD_FROM_NETWORK" << llendl; mFetcher->removeFromHTTPQueue(mID, 0); std::string reason(status.toString()); setGetStatus(status, reason); releaseHttpSemaphore(); - setState(INIT); + setState(LOAD_FROM_NETWORK); return; } else @@ -2559,7 +2559,7 @@ LLTextureFetch::~LLTextureFetch() } bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, - S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http, bool fake_failure) + S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http) { if(mFetcherLocked) { @@ -2633,7 +2633,6 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const worker->setDesiredDiscard(desired_discard, desired_size); worker->setCanUseHTTP(can_use_http); worker->setUrl(url); - worker->setFakeFailure(fake_failure); if (!worker->haveWork()) { worker->setState(LLTextureFetchWorker::INIT); @@ -2648,7 +2647,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const } else { - worker = new LLTextureFetchWorker(this, f_type, url, id, host, priority, desired_discard, desired_size, fake_failure); + worker = new LLTextureFetchWorker(this, f_type, url, id, host, priority, desired_discard, desired_size); lockQueue(); // +Mfq mRequestMap[id] = worker; unlockQueue(); // -Mfq @@ -3333,7 +3332,11 @@ bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size) void LLTextureFetchWorker::setState(e_state new_state) { - LL_DEBUGS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl; + if (mFTType == FTT_SERVER_BAKE) + { +// LL_INFOS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl; + } +// LL_DEBUGS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl; mState = new_state; } diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 12226d51c8..5e2b55dbbb 100755 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -78,7 +78,7 @@ public: // Threads: T* (but Tmain mostly) bool createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, - S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http, bool fake_failure); + S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http); // Requests that a fetch operation be deleted from the queue. // If @cancel is true, also stops any I/O operations pending. diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 8f7c8e40b7..45b402f0f6 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -962,8 +962,6 @@ void LLViewerFetchedTexture::init(bool firstinit) // does not contain this image. mIsMissingAsset = FALSE; - mFetchFailureCount = 0; - mLoadedCallbackDesiredDiscardLevel = S8_MAX; mPauseLoadedCallBacks = FALSE ; @@ -1826,35 +1824,17 @@ bool LLViewerFetchedTexture::updateFetch() // We finished but received no data if (current_discard < 0) { - const S32 MAX_FETCH_FAILURE = 1; - mFetchFailureCount++; if (getFTType() != FTT_MAP_TILE) { - llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount - << " status " << mLastHttpGetStatus.toHex() << llendl; - } - // Will retry server-bake textures under a limited set of circumstances. - if (getFTType() == FTT_SERVER_BAKE && - mLastHttpGetStatus.isHttpStatus() && - mLastHttpGetStatus.mType >= 500 && - mLastHttpGetStatus.mType <= 599 && // Only retry 5xx failures. - mFetchFailureCount < MAX_FETCH_FAILURE) - { - llwarns << "Will retry fetch" << llendl; - } - else // Otherwise, assume the image is missing. - { - if (getFTType() != FTT_MAP_TILE) - { - llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority - << " mRawDiscardLevel " << mRawDiscardLevel - << " current_discard " << current_discard - << " stats " << mLastHttpGetStatus.toHex() - << llendl; - } - setIsMissingAsset(); - desired_discard = -1; + llwarns << mID + << " Fetch failure, setting as missing, decode_priority " << decode_priority + << " mRawDiscardLevel " << mRawDiscardLevel + << " current_discard " << current_discard + << " stats " << mLastHttpGetStatus.toHex() + << llendl; } + setIsMissingAsset(); + desired_discard = -1; } else { @@ -1968,14 +1948,8 @@ bool LLViewerFetchedTexture::updateFetch() // bypass texturefetch directly by pulling from LLTextureCache bool fetch_request_created = false; - bool fake_failure = false; - const bool debug_setting_fake_failures = gSavedSettings.getBOOL("TextureFetchFakeFailures"); - if (getFTType() == FTT_SERVER_BAKE && mFetchFailureCount == 0 && debug_setting_fake_failures) - { - fake_failure = true; - } fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority, - w, h, c, desired_discard, needsAux(), mCanUseHTTP, fake_failure); + w, h, c, desired_discard, needsAux(), mCanUseHTTP); if (fetch_request_created) { @@ -2072,7 +2046,6 @@ void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing) else { llinfos << mID << ": un-flagging missing asset" << llendl; - mFetchFailureCount = 0; } mIsMissingAsset = is_missing; } diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 91e903ffd6..bf6aadd218 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -452,7 +452,6 @@ protected: FTType mFTType; // What category of image is this - map tile, server bake, etc? mutable BOOL mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. - S32 mFetchFailureCount; // How many times has a fetch failed in a way that suggests the asset is missing? typedef std::list callback_list_t; S8 mLoadedCallbackDesiredDiscardLevel; -- cgit v1.2.3 From 68cdbf387cf876da8833157b76048991120dc3f6 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 15 Apr 2013 18:03:31 -0400 Subject: SH-4061 WIP - comments, timing of retries --- indra/newview/lltexturefetch.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 2cebd4b6eb..7b719190a4 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -915,7 +915,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mCacheReadCount(0U), mCacheWriteCount(0U), mResourceWaitCount(0U), - mFetchRetryPolicy(15.0,15.0,1.0,10) + mFetchRetryPolicy(10.0,3600.0,2.0,10) { mCanUseNET = mUrl.empty() ; @@ -1981,7 +1981,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe F32 retry_after; if (mFetchRetryPolicy.shouldRetry(retry_after)) { - llinfos << mID << " should retry after " << retry_after << ", resetting state to LOAD_FROM_NETWORK" << llendl; + llinfos << mID << " will retry after " << retry_after << " seconds, resetting state to LOAD_FROM_NETWORK" << llendl; mFetcher->removeFromHTTPQueue(mID, 0); std::string reason(status.toString()); setGetStatus(status, reason); @@ -1991,7 +1991,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe } else { - llinfos << mID << " should not retry" << llendl; + llinfos << mID << " will not retry" << llendl; } } @@ -3334,9 +3334,12 @@ void LLTextureFetchWorker::setState(e_state new_state) { if (mFTType == FTT_SERVER_BAKE) { + // NOTE: turning on these log statements is a reliable way to get + // blurry images fairly frequently. Presumably this is an + // indication of some subtle timing or locking issue. + // LL_INFOS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl; } -// LL_DEBUGS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl; mState = new_state; } -- cgit v1.2.3 From 24b9657597be6d0b7af472d5deda4b4828ead606 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 15 Apr 2013 20:35:26 -0400 Subject: SH-4061 WIP - improved retry policy test, turned up and fixed a bug in getSecondsUntilRetryAfter --- indra/newview/tests/llhttpretrypolicy_test.cpp | 70 +++++++++++++------------- 1 file changed, 36 insertions(+), 34 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp index 42bb9abe90..6fa3a57364 100755 --- a/indra/newview/tests/llhttpretrypolicy_test.cpp +++ b/indra/newview/tests/llhttpretrypolicy_test.cpp @@ -216,21 +216,23 @@ void RetryPolicyTestObject::test<6>() time_t nowseconds; time(&nowseconds); - std::string str3 = LLDate((F64)nowseconds).asRFC1123(); + std::string str3 = LLDate((F64)(nowseconds+44)).asRFC1123(); seconds_to_wait = F32_MAX; success = getSecondsUntilRetryAfter(str3, seconds_to_wait); + std::cerr << " str3 [" << str3 << "]" << std::endl; ensure("parse 3", success); - ensure_approximately_equals("parse 3", seconds_to_wait, 0.0F, 6); + ensure_approximately_equals("parse 3", seconds_to_wait, 44.0F, 2); } // Test retry-after field in both llmessage and CoreHttp headers. template<> template<> void RetryPolicyTestObject::test<7>() { + std::cerr << "7 starts" << std::endl; + LLSD sd_headers; time_t nowseconds; time(&nowseconds); - sd_headers[HTTP_IN_HEADER_RETRY_AFTER] = LLDate((F64)nowseconds).asRFC1123(); LLAdaptiveRetryPolicy policy(17.0,644.0,3.0,5); F32 seconds_to_wait; bool should_retry; @@ -245,40 +247,40 @@ void RetryPolicyTestObject::test<7>() ensure_approximately_equals("header 1", seconds_to_wait, 17.0F, 6); // retry header should override, give delay of 0 + std::string date_string = LLDate((F64)(nowseconds+7)).asRFC1123(); + sd_headers[HTTP_IN_HEADER_RETRY_AFTER] = date_string; policy.onFailure(503,sd_headers); should_retry = policy.shouldRetry(seconds_to_wait); ensure("header 2", should_retry); - ensure_approximately_equals("header 2", seconds_to_wait, 0.0F, 6); - - // retry header in LLCore::HttpHeaders - { - LLCore::HttpResponse *response = new LLCore::HttpResponse(); - LLCore::HttpHeaders *headers = new LLCore::HttpHeaders(); - response->setStatus(503); - response->setHeaders(headers); - headers->append(HTTP_IN_HEADER_RETRY_AFTER, std::string("600")); - policy.onFailure(response); - should_retry = policy.shouldRetry(seconds_to_wait); - ensure("header 3",should_retry); - ensure_approximately_equals("header 3", seconds_to_wait, 600.0F, 6); - response->release(); - } - - // retry header in LLCore::HttpHeaders - { - LLCore::HttpResponse *response = new LLCore::HttpResponse(); - LLCore::HttpHeaders *headers = new LLCore::HttpHeaders(); - response->setStatus(503); - response->setHeaders(headers); - LLSD sd_headers; - time(&nowseconds); - headers->append(HTTP_IN_HEADER_RETRY_AFTER,LLDate((F64)nowseconds).asRFC1123()); - policy.onFailure(response); - should_retry = policy.shouldRetry(seconds_to_wait); - ensure("header 4",should_retry); - ensure_approximately_equals("header 4", seconds_to_wait, 0.0F, 6); - response->release(); - } + ensure_approximately_equals("header 2", seconds_to_wait, 7.0F, 2); + + LLCore::HttpResponse *response; + LLCore::HttpHeaders *headers; + + response = new LLCore::HttpResponse(); + headers = new LLCore::HttpHeaders(); + response->setStatus(503); + response->setHeaders(headers); + headers->append(HTTP_IN_HEADER_RETRY_AFTER, std::string("600")); + policy.onFailure(response); + should_retry = policy.shouldRetry(seconds_to_wait); + ensure("header 3",should_retry); + ensure_approximately_equals("header 3", seconds_to_wait, 600.0F, 6); + response->release(); + + response = new LLCore::HttpResponse(); + headers = new LLCore::HttpHeaders(); + response->setStatus(503); + response->setHeaders(headers); + time(&nowseconds); + date_string = LLDate((F64)(nowseconds+77)).asRFC1123(); + std::cerr << "date_string [" << date_string << "]" << std::endl; + headers->append(HTTP_IN_HEADER_RETRY_AFTER,date_string); + policy.onFailure(response); + should_retry = policy.shouldRetry(seconds_to_wait); + ensure("header 4",should_retry); + ensure_approximately_equals("header 4", seconds_to_wait, 77.0F, 2); + response->release(); // Timeout should be clamped at max. policy.onFailure(500,LLSD()); -- cgit v1.2.3 From 9cbbb45a0ca8a56707125cdb3f6ea95de7f9deef Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 16 Apr 2013 09:19:35 -0400 Subject: SH-4061 WIP - cleanup --- indra/newview/lltexturefetch.cpp | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index ce7bd61ce4..1a6a308230 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1609,24 +1609,6 @@ bool LLTextureFetchWorker::doWork(S32 param) << " Reason: '" << mGetReason << "'" << llendl; } -#if 0 - if (isHttpServerErrorStatus(mGetStatus.mType)) - { - // Check for retry - F32 wait_seconds; - if (mFetchRetryPolicy.shouldRetry(wait_seconds)) - { - llinfos << mID << " status " << (S32) mGetStatus.mType << " will retry after " << wait_seconds << llendl; - setState(INIT); - releaseHttpSemaphore(); - return false; - } - else - { - llinfos << mID << " will not retry on status " << (S32) mGetStatus.mType << llendl; - } - } -#endif mUrl.clear(); if (cur_size > 0) -- cgit v1.2.3 From 0a413e1dc82bbe18c5c9fe510b10e33f8fb0a93c Mon Sep 17 00:00:00 2001 From: "prep@lindenlab.com" Date: Tue, 16 Apr 2013 11:54:16 -0500 Subject: Fix for SH-4108 - observer does not see the outfit change when closing appearance panel. --- indra/newview/llsidepanelappearance.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/newview') diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 7b89e0617b..3c21219dc1 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -136,6 +136,7 @@ void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj) } else { + LLVOAvatarSelf::onCustomizeEnd(FALSE); mLLFloaterSidePanelContainer->close(); } } -- cgit v1.2.3 From e3bad9fb86c3f44ad67488402ce2e46743a2422e Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 16 Apr 2013 20:27:49 -0400 Subject: SH-4061 WIP - fix for build issues on mac, reset the retry policy on success. --- indra/newview/llhttpretrypolicy.cpp | 18 ++++++++++--- indra/newview/llhttpretrypolicy.h | 16 +++++++++--- indra/newview/lltexturefetch.cpp | 4 +++ indra/newview/tests/llhttpretrypolicy_test.cpp | 35 +++++++++++++++++++++----- 4 files changed, 59 insertions(+), 14 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp index 10b923be5a..80d97e4362 100755 --- a/indra/newview/llhttpretrypolicy.cpp +++ b/indra/newview/llhttpretrypolicy.cpp @@ -32,11 +32,16 @@ LLAdaptiveRetryPolicy::LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 b mMinDelay(min_delay), mMaxDelay(max_delay), mBackoffFactor(backoff_factor), - mMaxRetries(max_retries), - mDelay(min_delay), - mRetryCount(0), - mShouldRetry(true) + mMaxRetries(max_retries) { + init(); +} + +void LLAdaptiveRetryPolicy::init() +{ + mDelay = mMinDelay; + mRetryCount = 0; + mShouldRetry = true; } bool LLAdaptiveRetryPolicy::getRetryAfter(const LLSD& headers, F32& retry_header_time) @@ -59,6 +64,11 @@ bool LLAdaptiveRetryPolicy::getRetryAfter(const LLCore::HttpHeaders *headers, F3 return false; } +void LLAdaptiveRetryPolicy::onSuccess() +{ + init(); +} + void LLAdaptiveRetryPolicy::onFailure(S32 status, const LLSD& headers) { F32 retry_header_time; diff --git a/indra/newview/llhttpretrypolicy.h b/indra/newview/llhttpretrypolicy.h index 6f63f047de..1fb0cac03f 100755 --- a/indra/newview/llhttpretrypolicy.h +++ b/indra/newview/llhttpretrypolicy.h @@ -42,7 +42,11 @@ class LLHTTPRetryPolicy: public LLThreadSafeRefCount { public: LLHTTPRetryPolicy() {} + virtual ~LLHTTPRetryPolicy() {} + // Call after a sucess to reset retry state. + + virtual void onSuccess() = 0; // Call once after an HTTP failure to update state. virtual void onFailure(S32 status, const LLSD& headers) = 0; @@ -58,6 +62,9 @@ class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy public: LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries); + // virtual + void onSuccess(); + // virtual void onFailure(S32 status, const LLSD& headers); // virtual @@ -66,16 +73,17 @@ public: bool shouldRetry(F32& seconds_to_wait) const; protected: + void init(); bool getRetryAfter(const LLSD& headers, F32& retry_header_time); bool getRetryAfter(const LLCore::HttpHeaders *headers, F32& retry_header_time); void onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time); private: - F32 mMinDelay; // delay never less than this value - F32 mMaxDelay; // delay never exceeds this value - F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay. - U32 mMaxRetries; // maximum number of times shouldRetry will return true. + const F32 mMinDelay; // delay never less than this value + const F32 mMaxDelay; // delay never exceeds this value + const F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay. + const U32 mMaxRetries; // maximum number of times shouldRetry will return true. F32 mDelay; // current default delay. U32 mRetryCount; // number of times shouldRetry has been called. LLTimer mRetryTimer; // time until next retry. diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 1a6a308230..774c925fa1 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1976,6 +1976,10 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe llinfos << mID << " will not retry" << llendl; } } + else + { + mFetchRetryPolicy.onSuccess(); + } LL_DEBUGS("Texture") << "HTTP COMPLETE: " << mID << " status: " << status.toHex() diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp index 6fa3a57364..ed7f3ba326 100755 --- a/indra/newview/tests/llhttpretrypolicy_test.cpp +++ b/indra/newview/tests/llhttpretrypolicy_test.cpp @@ -45,7 +45,7 @@ void RetryPolicyTestObject::test<1>() LLSD headers; F32 wait_seconds; - // No retry until we've finished a try. + // No retry until we've failed a try. ensure("never retry 0", !never_retry.shouldRetry(wait_seconds)); // 0 retries max. @@ -74,7 +74,7 @@ void RetryPolicyTestObject::test<3>() bool should_retry; U32 frac_bits = 6; - // No retry until we've finished a try. + // No retry until we've failed a try. ensure("basic_retry 0", !basic_retry.shouldRetry(wait_seconds)); // Starting wait 1.0 @@ -105,6 +105,29 @@ void RetryPolicyTestObject::test<3>() basic_retry.onFailure(500,headers); should_retry = basic_retry.shouldRetry(wait_seconds); ensure("basic_retry 5", !should_retry); + + // Max retries, should fail now. + basic_retry.onFailure(500,headers); + should_retry = basic_retry.shouldRetry(wait_seconds); + ensure("basic_retry 5", !should_retry); + + // After a success, should reset to the starting state. + basic_retry.onSuccess(); + + // No retry until we've failed a try. + ensure("basic_retry 6", !basic_retry.shouldRetry(wait_seconds)); + + // Starting wait 1.0 + basic_retry.onFailure(500,headers); + should_retry = basic_retry.shouldRetry(wait_seconds); + ensure("basic_retry 7", should_retry); + ensure_approximately_equals("basic_retry 7", wait_seconds, 1.0F, frac_bits); + + // Double wait to 2.0 + basic_retry.onFailure(500,headers); + should_retry = basic_retry.shouldRetry(wait_seconds); + ensure("basic_retry 8", should_retry); + ensure_approximately_equals("basic_retry 8", wait_seconds, 2.0F, frac_bits); } // Retries should stop as soon as a non-5xx error is received. @@ -221,7 +244,7 @@ void RetryPolicyTestObject::test<6>() success = getSecondsUntilRetryAfter(str3, seconds_to_wait); std::cerr << " str3 [" << str3 << "]" << std::endl; ensure("parse 3", success); - ensure_approximately_equals("parse 3", seconds_to_wait, 44.0F, 2); + ensure_approximately_equals_range("parse 3", seconds_to_wait, 44.0F, 2.0F); } // Test retry-after field in both llmessage and CoreHttp headers. @@ -237,7 +260,7 @@ void RetryPolicyTestObject::test<7>() F32 seconds_to_wait; bool should_retry; - // No retry until we've finished a try. + // No retry until we've failed a try. ensure("header 0", !policy.shouldRetry(seconds_to_wait)); // no retry header, use default. @@ -252,7 +275,7 @@ void RetryPolicyTestObject::test<7>() policy.onFailure(503,sd_headers); should_retry = policy.shouldRetry(seconds_to_wait); ensure("header 2", should_retry); - ensure_approximately_equals("header 2", seconds_to_wait, 7.0F, 2); + ensure_approximately_equals_range("header 2", seconds_to_wait, 7.0F, 2.0F); LLCore::HttpResponse *response; LLCore::HttpHeaders *headers; @@ -279,7 +302,7 @@ void RetryPolicyTestObject::test<7>() policy.onFailure(response); should_retry = policy.shouldRetry(seconds_to_wait); ensure("header 4",should_retry); - ensure_approximately_equals("header 4", seconds_to_wait, 77.0F, 2); + ensure_approximately_equals_range("header 4", seconds_to_wait, 77.0F, 2.0F); response->release(); // Timeout should be clamped at max. -- cgit v1.2.3 From 8cf67fe50cfa070e5aa786acdb9bce58c350d840 Mon Sep 17 00:00:00 2001 From: prep Date: Wed, 17 Apr 2013 10:33:33 -0400 Subject: Fix for SH-4104: Inventory window does not close --- indra/newview/llfloatersidepanelcontainer.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index b1f9a18d6f..4dd558c9c0 100644 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -69,6 +69,10 @@ void LLFloaterSidePanelContainer::onClickCloseBtn() LLSidepanelAppearance* panel_appearance = dynamic_cast(getPanel("appearance")); panel_appearance->onClose(this); } + else + { + LLFloater::onClickCloseBtn(); + } } else { -- cgit v1.2.3 From 392f561b6c28aede2b61bc9cc2cc75de587926b6 Mon Sep 17 00:00:00 2001 From: prep Date: Wed, 17 Apr 2013 11:08:40 -0400 Subject: Fix for SH-4123: outfit update corrected for edit/save/abandon sequence --- indra/newview/llsidepanelappearance.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 3c21219dc1..75da23b558 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -90,8 +90,9 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if ( option == 0 ) { + //revert curernt edits mEditWearable->revertChanges(); - LLAppearanceMgr::getInstance()->wearBaseOutfit(); + LLVOAvatarSelf::onCustomizeEnd(FALSE); mLLFloaterSidePanelContainer->close(); return true; } -- cgit v1.2.3 From b224b8978adfd42c89e1c66bc5495ead8fa1e85d Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 17 Apr 2013 11:32:23 -0400 Subject: SH-4061 WIP - request headers for server-bake images --- indra/newview/lltexturefetch.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 774c925fa1..346374ef4e 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1524,12 +1524,14 @@ bool LLTextureFetchWorker::doWork(S32 param) << LL_ENDL; // Will call callbackHttpGet when curl request completes + // Only server bake images use the returned headers currently, for getting retry-after field. + HttpOptions *options = (mFTType == FTT_SERVER_BAKE) ? mFetcher->mHttpOptionsWithHeaders: mFetcher->mHttpOptions; mHttpHandle = mFetcher->mHttpRequest->requestGetByteRange(mHttpPolicyClass, mWorkPriority, mUrl, mRequestedOffset, mRequestedSize, - mFetcher->mHttpOptions, + options, mFetcher->mHttpHeaders, this); } -- cgit v1.2.3 From b29e6f656eb28d557ef4488a022b6757a58d29e1 Mon Sep 17 00:00:00 2001 From: prep Date: Wed, 17 Apr 2013 11:32:49 -0400 Subject: Fix for SH-4124: Closing appearance panel also closes the edit wearable panel if it was active --- indra/newview/llsidepanelappearance.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 75da23b558..77e9604460 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -92,6 +92,7 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica { //revert curernt edits mEditWearable->revertChanges(); + toggleWearableEditPanel(FALSE); LLVOAvatarSelf::onCustomizeEnd(FALSE); mLLFloaterSidePanelContainer->close(); return true; @@ -138,6 +139,7 @@ void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj) else { LLVOAvatarSelf::onCustomizeEnd(FALSE); + toggleWearableEditPanel(FALSE); mLLFloaterSidePanelContainer->close(); } } -- cgit v1.2.3 From 17af76fae18e305d0a42192a326648f00c84d1f3 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 18 Apr 2013 13:56:16 -0400 Subject: SH-4128 WIP - use the AISv3 inventory cap when available for cof link deletion, hook in to callback mechanism so all link operations should be done before outfit is worn. --- indra/newview/llappearancemgr.cpp | 20 ++----- indra/newview/llappearancemgr.h | 2 +- indra/newview/lltexturefetch.cpp | 4 +- indra/newview/llviewerinventory.cpp | 101 ++++++++++++++++++++++++++++++++++++ indra/newview/llviewerinventory.h | 4 ++ indra/newview/llviewerregion.cpp | 1 + 6 files changed, 113 insertions(+), 19 deletions(-) mode change 100644 => 100755 indra/newview/llviewerinventory.cpp mode change 100644 => 100755 indra/newview/llviewerinventory.h (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 85f6f92278..f1a2141b99 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1661,7 +1661,7 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category) } } -void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_links, LLInventoryModel::item_array_t* keep_items) +void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_links, LLPointer cb) { LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; @@ -1674,19 +1674,8 @@ void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_lin continue; if (item->getIsLinkType()) { -#if 0 - if (keep_items && keep_items->find(item) != LLInventoryModel::item_array_t::FAIL) - { - llinfos << "preserved item" << llendl; - } - else - { - gInventory.purgeObject(item->getUUID()); - } -#else - gInventory.purgeObject(item->getUUID()); + remove_inventory_item(item->getUUID(), cb); } -#endif } } @@ -1819,7 +1808,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) // carried over (e.g. keeping old shape if the new outfit does not // contain one) bool keep_outfit_links = append; - purgeCategory(cof, keep_outfit_links, &all_items); + purgeCategory(cof, keep_outfit_links, link_waiter); gInventory.notifyObservers(); LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL; @@ -2824,7 +2813,7 @@ bool LLAppearanceMgr::updateBaseOutfit() updateClothingOrderingInfo(); // in a Base Outfit we do not remove items, only links - purgeCategory(base_outfit_id, false); + purgeCategory(base_outfit_id, false, NULL); LLPointer dirty_state_updater = new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state); @@ -3211,7 +3200,6 @@ void LLAppearanceMgr::requestServerAppearanceUpdate(LLCurl::ResponderPtr respond } LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << llendl; - //LLCurl::ResponderPtr responder_ptr; if (!responder_ptr.get()) { responder_ptr = new RequestAgentUpdateAppearanceResponder; diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 46252afbde..b933b4fc50 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -222,7 +222,7 @@ private: LLInventoryModel::item_array_t& gest_items, bool follow_folder_links); - void purgeCategory(const LLUUID& category, bool keep_outfit_links, LLInventoryModel::item_array_t* keep_items = NULL); + void purgeCategory(const LLUUID& category, bool keep_outfit_links, LLPointer cb); static void onOutfitRename(const LLSD& notification, const LLSD& response); void setOutfitLocked(bool locked); diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 346374ef4e..f7fbb19bdc 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1525,7 +1525,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // Will call callbackHttpGet when curl request completes // Only server bake images use the returned headers currently, for getting retry-after field. - HttpOptions *options = (mFTType == FTT_SERVER_BAKE) ? mFetcher->mHttpOptionsWithHeaders: mFetcher->mHttpOptions; + LLCore::HttpOptions *options = (mFTType == FTT_SERVER_BAKE) ? mFetcher->mHttpOptionsWithHeaders: mFetcher->mHttpOptions; mHttpHandle = mFetcher->mHttpRequest->requestGetByteRange(mHttpPolicyClass, mWorkPriority, mUrl, @@ -2569,7 +2569,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const if (f_type == FTT_SERVER_BAKE) { - llinfos << " requesting " << id << " " << w << "x" << h << " discard " << desired_discard << llendl; + LL_DEBUGS("Avatar") << " requesting " << id << " " << w << "x" << h << " discard " << desired_discard << llendl; } LLTextureFetchWorker* worker = getWorker(id) ; if (worker) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp old mode 100644 new mode 100755 index fff9821e86..316fca7769 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1179,6 +1179,107 @@ void move_inventory_item( gAgent.sendReliableMessage(); } +void handle_item_deletion(const LLUUID& item_id) +{ + LLPointer obj = gInventory.getItem(item_id); + if(obj) + { + // From item removeFromServer() + LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1); + gInventory.accountForUpdate(up); + + // From purgeObject() + LLPreview::hide(item_id); + gInventory.deleteObject(item_id); + } +} + +class RemoveItemResponder: public LLHTTPClient::Responder +{ +public: + RemoveItemResponder(const LLUUID& item_id, LLPointer callback): + mItemUUID(item_id), + mCallback(callback) + { + } + /* virtual */ void httpSuccess() + { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + llinfos << "succeeded: " << ll_pretty_print_sd(content) << llendl; + + handle_item_deletion(mItemUUID); + + if (mCallback) + { + mCallback->fire(mItemUUID); + } + } + /*virtual*/ void httpFailure() + { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << llendl; + } +private: + LLPointer mCallback; + const LLUUID mItemUUID; +}; + +void remove_inventory_item( + const LLUUID& item_id, + LLPointer cb) +{ + llinfos << "item_id: [" << item_id << "] " << llendl; + LLPointer obj = gInventory.getItem(item_id); + if(obj) + { + std::string cap; + if (gAgent.getRegion()) + { + cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); + } + if (!cap.empty()) + { + std::string url = cap + std::string("/item/") + item_id.asString(); + llinfos << "url: " << url << llendl; + LLCurl::ResponderPtr responder_ptr = new RemoveItemResponder(item_id,cb); + LLHTTPClient::del(url,responder_ptr); + } + else // no cap + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RemoveInventoryItem); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addUUIDFast(_PREHASH_ItemID, item_id); + gAgent.sendReliableMessage(); + + // Update inventory and call callback immediately since + // message-based system has no callback mechanism (!) + handle_item_deletion(item_id); + if (cb) + { + cb->fire(item_id); + } + } + } + else + { + llwarns << "remove_inventory_item called for nonexistent item " << item_id << llendl; + } +} + const LLUUID get_folder_by_itemtype(const LLInventoryItem *src) { LLUUID retval = LLUUID::null; diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h old mode 100644 new mode 100755 index 61b1b8d846..7cb62efb47 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -365,6 +365,10 @@ void move_inventory_item( const std::string& new_name, LLPointer cb); +void remove_inventory_item( + const LLUUID& item_id, + LLPointer cb); + const LLUUID get_folder_by_itemtype(const LLInventoryItem *src); void copy_inventory_from_notecard(const LLUUID& destination_id, diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index f0d81c599c..e77b29aca4 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1641,6 +1641,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("FetchInventory2"); capabilityNames.append("FetchInventoryDescendents2"); capabilityNames.append("IncrementCOFVersion"); + capabilityNames.append("InventoryAPIv3"); } capabilityNames.append("GetDisplayNames"); -- 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') 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/llappearancemgr.cpp | 49 ++++++++++++++++---------------------- indra/newview/llappearancemgr.h | 6 ++--- indra/newview/llinventorymodel.cpp | 33 +------------------------ indra/newview/llinventorymodel.h | 3 +-- 4 files changed, 24 insertions(+), 67 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index f1a2141b99..fffec223d7 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1204,8 +1204,7 @@ const LLViewerInventoryItem* LLAppearanceMgr::getBaseOutfitLink() cat_array, item_array, false, - is_category, - false); + is_category); for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); iter != item_array.end(); iter++) @@ -1738,7 +1737,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) if (!append) { LLInventoryModel::item_array_t gest_items; - getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE, false); + getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE); for(S32 i = 0; i < gest_items.count(); ++i) { LLViewerInventoryItem *gest_item = gest_items.get(i); @@ -1755,8 +1754,8 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) // required parts are missing. // Preserve body parts from COF if appending. LLInventoryModel::item_array_t body_items; - getDescendentsOfAssetType(cof, body_items, LLAssetType::AT_BODYPART, false); - getDescendentsOfAssetType(category, body_items, LLAssetType::AT_BODYPART, false); + getDescendentsOfAssetType(cof, body_items, LLAssetType::AT_BODYPART); + getDescendentsOfAssetType(category, body_items, LLAssetType::AT_BODYPART); if (append) reverse(body_items.begin(), body_items.end()); // Reduce body items to max of one per type. @@ -1766,8 +1765,8 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) // - Wearables: include COF contents only if appending. LLInventoryModel::item_array_t wear_items; if (append) - getDescendentsOfAssetType(cof, wear_items, LLAssetType::AT_CLOTHING, false); - getDescendentsOfAssetType(category, wear_items, LLAssetType::AT_CLOTHING, false); + getDescendentsOfAssetType(cof, wear_items, LLAssetType::AT_CLOTHING); + getDescendentsOfAssetType(category, wear_items, LLAssetType::AT_CLOTHING); // Reduce wearables to max of one per type. removeDuplicateItems(wear_items); filterWearableItems(wear_items, LLAgentWearables::MAX_CLOTHING_PER_TYPE); @@ -1775,15 +1774,15 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) // - Attachments: include COF contents only if appending. LLInventoryModel::item_array_t obj_items; if (append) - getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT, false); - getDescendentsOfAssetType(category, obj_items, LLAssetType::AT_OBJECT, false); + getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT); + getDescendentsOfAssetType(category, obj_items, LLAssetType::AT_OBJECT); removeDuplicateItems(obj_items); // - Gestures: include COF contents only if appending. LLInventoryModel::item_array_t gest_items; if (append) - getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE, false); - getDescendentsOfAssetType(category, gest_items, LLAssetType::AT_GESTURE, false); + getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE); + getDescendentsOfAssetType(category, gest_items, LLAssetType::AT_GESTURE); removeDuplicateItems(gest_items); // Create links to new COF contents. @@ -1927,7 +1926,7 @@ S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id, S32 to_kill_count = 0; LLInventoryModel::item_array_t items; - getDescendentsOfAssetType(cat_id, items, type, false); + getDescendentsOfAssetType(cat_id, items, type); LLInventoryModel::item_array_t curr_items = items; removeDuplicateItems(items); if (max_items > 0) @@ -2009,7 +2008,6 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) //dumpCat(getCOF(),"COF, start"); - bool follow_folder_links = false; LLUUID current_outfit_id = getCOF(); // Find all the wearables that are in the COF's subtree. @@ -2017,7 +2015,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) LLInventoryModel::item_array_t wear_items; LLInventoryModel::item_array_t obj_items; LLInventoryModel::item_array_t gest_items; - getUserDescendents(current_outfit_id, wear_items, obj_items, gest_items, follow_folder_links); + getUserDescendents(current_outfit_id, wear_items, obj_items, gest_items); // Get rid of non-links in case somehow the COF was corrupted. remove_non_link_items(wear_items); remove_non_link_items(obj_items); @@ -2113,8 +2111,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) void LLAppearanceMgr::getDescendentsOfAssetType(const LLUUID& category, LLInventoryModel::item_array_t& items, - LLAssetType::EType type, - bool follow_folder_links) + LLAssetType::EType type) { LLInventoryModel::cat_array_t cats; LLIsType is_of_type(type); @@ -2122,15 +2119,13 @@ void LLAppearanceMgr::getDescendentsOfAssetType(const LLUUID& category, cats, items, LLInventoryModel::EXCLUDE_TRASH, - is_of_type, - follow_folder_links); + is_of_type); } void LLAppearanceMgr::getUserDescendents(const LLUUID& category, LLInventoryModel::item_array_t& wear_items, LLInventoryModel::item_array_t& obj_items, - LLInventoryModel::item_array_t& gest_items, - bool follow_folder_links) + LLInventoryModel::item_array_t& gest_items) { LLInventoryModel::cat_array_t wear_cats; LLFindWearables is_wearable; @@ -2138,8 +2133,7 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category, wear_cats, wear_items, LLInventoryModel::EXCLUDE_TRASH, - is_wearable, - follow_folder_links); + is_wearable); LLInventoryModel::cat_array_t obj_cats; LLIsType is_object( LLAssetType::AT_OBJECT ); @@ -2147,8 +2141,7 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category, obj_cats, obj_items, LLInventoryModel::EXCLUDE_TRASH, - is_object, - follow_folder_links); + is_object); // Find all gestures in this folder LLInventoryModel::cat_array_t gest_cats; @@ -2157,8 +2150,7 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category, gest_cats, gest_items, LLInventoryModel::EXCLUDE_TRASH, - is_gesture, - follow_folder_links); + is_gesture); } void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append) @@ -2514,8 +2506,7 @@ void LLAppearanceMgr::removeAllClothesFromAvatar() dummy, clothing_items, LLInventoryModel::EXCLUDE_TRASH, - is_clothing, - false); + is_clothing); uuid_vec_t item_ids; for (LLInventoryModel::item_array_t::iterator it = clothing_items.begin(); it != clothing_items.end(); ++it) @@ -2910,7 +2901,7 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base // COF is processed if cat_id is not specified LLInventoryModel::item_array_t wear_items; - getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING, false); + getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING); wearables_by_type_t items_by_type(LLWearableType::WT_COUNT); divvyWearablesByType(wear_items, items_by_type); diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index b933b4fc50..6c014b1a4b 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -213,14 +213,12 @@ private: void getDescendentsOfAssetType(const LLUUID& category, LLInventoryModel::item_array_t& items, - LLAssetType::EType type, - bool follow_folder_links); + LLAssetType::EType type); void getUserDescendents(const LLUUID& category, LLInventoryModel::item_array_t& wear_items, LLInventoryModel::item_array_t& obj_items, - LLInventoryModel::item_array_t& gest_items, - bool follow_folder_links); + LLInventoryModel::item_array_t& gest_items); void purgeCategory(const LLUUID& category, bool keep_outfit_links, LLPointer cb); static void onOutfitRename(const LLSD& notification, const LLSD& response); 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) { diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 3aa29bd91d..0b017b7514 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -213,8 +213,7 @@ public: cat_array_t& categories, item_array_t& items, BOOL include_trash, - LLInventoryCollectFunctor& add, - BOOL follow_folder_links = FALSE); + LLInventoryCollectFunctor& add); // Collect all items in inventory that are linked to item_id. // Assumes item_id is itself not a linked item. -- cgit v1.2.3 From d807a9162662aa3b921020af2df2c30cc71b1b32 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 22 Apr 2013 16:48:02 -0400 Subject: SH-4128 WIP - more stages of outfit change now go through the callback mechanism for link removals --- indra/newview/llappearancemgr.cpp | 89 +++++++++++++++++++++++---------------- indra/newview/llappearancemgr.h | 17 ++++++-- 2 files changed, 66 insertions(+), 40 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index fffec223d7..21af5adf09 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -501,9 +501,11 @@ public: } }; -LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering): +LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering, + bool enforce_item_restrictions): mFireCount(0), - mUpdateBaseOrder(update_base_outfit_ordering) + mUpdateBaseOrder(update_base_outfit_ordering), + mEnforceItemRestrictions(enforce_item_restrictions) { selfStartPhase("update_appearance_on_destroy"); } @@ -517,7 +519,7 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy() selfStopPhase("update_appearance_on_destroy"); - LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder); + LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder, mEnforceItemRestrictions); } } @@ -1660,7 +1662,8 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category) } } -void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_links, LLPointer cb) +void LLAppearanceMgr::removeCategoryContents(const LLUUID& category, bool keep_outfit_links, + LLPointer cb) { LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; @@ -1726,6 +1729,18 @@ void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid, } } +void LLAppearanceMgr::removeAll(LLInventoryModel::item_array_t& items_to_kill, + LLPointer cb) +{ + for (LLInventoryModel::item_array_t::iterator it = items_to_kill.begin(); + it != items_to_kill.end(); + ++it) + { + LLViewerInventoryItem *item = *it; + remove_inventory_item(item->getUUID(), cb); + } +} + void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) { LLViewerInventoryCategory *pcat = gInventory.getCategory(category); @@ -1807,8 +1822,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) // carried over (e.g. keeping old shape if the new outfit does not // contain one) bool keep_outfit_links = append; - purgeCategory(cof, keep_outfit_links, link_waiter); - gInventory.notifyObservers(); + removeCategoryContents(cof, keep_outfit_links, link_waiter); LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL; } @@ -1945,34 +1959,20 @@ S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id, return to_kill_count; } - -void LLAppearanceMgr::enforceItemRestrictions() -{ - S32 purge_count = 0; - LLInventoryModel::item_array_t items_to_kill; - - purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_BODYPART, - 1, items_to_kill); - purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_CLOTHING, - LLAgentWearables::MAX_CLOTHING_PER_TYPE, items_to_kill); - purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_OBJECT, - -1, items_to_kill); - if (items_to_kill.size()>0) - { - for (LLInventoryModel::item_array_t::iterator it = items_to_kill.begin(); - it != items_to_kill.end(); - ++it) - { - LLViewerInventoryItem *item = *it; - LL_DEBUGS("Avatar") << self_av_string() << "purging duplicate or excess item " << item->getName() << LL_ENDL; - gInventory.purgeObject(item->getUUID()); - } - gInventory.notifyObservers(); - } +void LLAppearanceMgr::findAllExcessOrDuplicateItems(const LLUUID& cat_id, + LLInventoryModel::item_array_t& items_to_kill) +{ + findExcessOrDuplicateItems(cat_id,LLAssetType::AT_BODYPART, + 1, items_to_kill); + findExcessOrDuplicateItems(cat_id,LLAssetType::AT_CLOTHING, + LLAgentWearables::MAX_CLOTHING_PER_TYPE, items_to_kill); + findExcessOrDuplicateItems(cat_id,LLAssetType::AT_OBJECT, + -1, items_to_kill); } -void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) +void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering, + bool enforce_item_restrictions) { if (mIsInUpdateAppearanceFromCOF) { @@ -1985,14 +1985,31 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) LL_DEBUGS("Avatar") << self_av_string() << "starting" << LL_ENDL; + if (enforce_item_restrictions) + { + LLInventoryModel::item_array_t items_to_kill; + findAllExcessOrDuplicateItems(getCOF(), items_to_kill); + if (items_to_kill.size()>0) + { + // The point here is just to call + // updateAppearanceFromCOF() again after excess items + // have been removed. That time we will set + // enforce_item_restrictions to false so we don't get + // caught in a perpetual loop. + LLPointer cb( + new LLUpdateAppearanceOnDestroy(update_base_outfit_ordering, false)); + + // Remove duplicate or excess wearables. Should normally be enforced at the UI level, but + // this should catch anything that gets through. + removeAll(items_to_kill, cb); + return; + } + } + //checking integrity of the COF in terms of ordering of wearables, //checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state) updateClothingOrderingInfo(LLUUID::null, update_base_outfit_ordering); - // Remove duplicate or excess wearables. Should normally be enforced at the UI level, but - // this should catch anything that gets through. - enforceItemRestrictions(); - // update dirty flag to see if the state of the COF matches // the saved outfit stored as a folder link updateIsDirty(); @@ -2804,7 +2821,7 @@ bool LLAppearanceMgr::updateBaseOutfit() updateClothingOrderingInfo(); // in a Base Outfit we do not remove items, only links - purgeCategory(base_outfit_id, false, NULL); + removeCategoryContents(base_outfit_id, false, NULL); LLPointer dirty_state_updater = new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state); diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 6c014b1a4b..0cc06ab210 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -49,7 +49,8 @@ class LLAppearanceMgr: public LLSingleton public: typedef std::vector wearables_by_type_t; - void updateAppearanceFromCOF(bool update_base_outfit_ordering = false); + void updateAppearanceFromCOF(bool update_base_outfit_ordering = false, + bool enforce_item_restrictions = true); bool needToSaveCOF(); void updateCOF(const LLUUID& category, bool append = false); void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append); @@ -65,7 +66,8 @@ public: LLAssetType::EType type, S32 max_items, LLInventoryModel::item_array_t& items_to_kill); - void enforceItemRestrictions(); + void findAllExcessOrDuplicateItems(const LLUUID& cat_id, + LLInventoryModel::item_array_t& items_to_kill); // Copy all items and the src category itself. void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id, @@ -129,6 +131,10 @@ public: LLInventoryModel::item_array_t& items, LLPointer cb); + // And bulk removal. + void removeAll(LLInventoryModel::item_array_t& items, + LLPointer cb); + // Add COF link to individual item. void addCOFItemLink(const LLUUID& item_id, bool do_update = true, LLPointer cb = NULL, const std::string description = ""); void addCOFItemLink(const LLInventoryItem *item, bool do_update = true, LLPointer cb = NULL, const std::string description = ""); @@ -220,7 +226,8 @@ private: LLInventoryModel::item_array_t& obj_items, LLInventoryModel::item_array_t& gest_items); - void purgeCategory(const LLUUID& category, bool keep_outfit_links, LLPointer cb); + void removeCategoryContents(const LLUUID& category, bool keep_outfit_links, + LLPointer cb); static void onOutfitRename(const LLSD& notification, const LLSD& response); void setOutfitLocked(bool locked); @@ -254,13 +261,15 @@ public: class LLUpdateAppearanceOnDestroy: public LLInventoryCallback { public: - LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering = false); + LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering = false, + bool enforce_item_restrictions = true); virtual ~LLUpdateAppearanceOnDestroy(); /* virtual */ void fire(const LLUUID& inv_item); private: U32 mFireCount; bool mUpdateBaseOrder; + bool mEnforceItemRestrictions; }; -- cgit v1.2.3 From 1bf66885617564c8df9baac3b45ed5e9d96ef153 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 23 Apr 2013 15:52:12 -0400 Subject: SH-4128 WIP - rewiring various link-deleting operations to support callbacks --- indra/newview/llagentwearables.cpp | 9 +- indra/newview/llappearancemgr.cpp | 203 ++++++++++++------------------------ indra/newview/llappearancemgr.h | 27 +++-- indra/newview/llfloatergesture.cpp | 2 +- indra/newview/llpaneloutfitedit.cpp | 4 +- indra/newview/llviewerinventory.h | 2 +- 6 files changed, 95 insertions(+), 152 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index c88694ef76..b4c3e33e0e 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -69,7 +69,7 @@ void wear_and_edit_cb(const LLUUID& inv_item) gAgentWearables.requestEditingWearable(inv_item); // Wear it. - LLAppearanceMgr::instance().wearItemOnAvatar(inv_item); + LLAppearanceMgr::instance().wearItemOnAvatar(inv_item,true); } /////////////////////////////////////////////////////////////////////////////// @@ -239,7 +239,7 @@ void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& i } if (mTodo & CALL_RECOVERDONE) { - LLAppearanceMgr::instance().addCOFItemLink(inv_item,false); + LLAppearanceMgr::instance().addCOFItemLink(inv_item); gAgentWearables.recoverMissingWearableDone(); } /* @@ -247,7 +247,7 @@ void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& i */ if (mTodo & CALL_CREATESTANDARDDONE) { - LLAppearanceMgr::instance().addCOFItemLink(inv_item,false); + LLAppearanceMgr::instance().addCOFItemLink(inv_item); gAgentWearables.createStandardWearablesDone(mType, mIndex); } if (mTodo & CALL_MAKENEWOUTFITDONE) @@ -256,7 +256,8 @@ void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& i } if (mTodo & CALL_WEARITEM) { - LLAppearanceMgr::instance().addCOFItemLink(inv_item, true, NULL, mDescription); + LLAppearanceMgr::instance().addCOFItemLink(inv_item, + new LLUpdateAppearanceAndEditWearableOnDestroy(inv_item), mDescription); } } diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 21af5adf09..634f5d1389 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -421,86 +421,6 @@ public: } }; -class LLCallAfterInventoryLinkMgr: public LLCallAfterInventoryBatchMgr -{ -public: - LLCallAfterInventoryLinkMgr(LLInventoryModel::item_array_t& src_items, - const LLUUID& dst_cat_id, - const std::string& phase_name, - nullary_func_t on_completion_func, - nullary_func_t on_failure_func = no_op, - F32 retry_after = DEFAULT_RETRY_AFTER_INTERVAL, - S32 max_retries = DEFAULT_MAX_RETRIES - ): - LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func, retry_after, max_retries) - { - addItems(src_items); - } - - virtual bool requestOperation(const LLUUID& item_id) - { - bool request_sent = false; - LLViewerInventoryItem *item = gInventory.getItem(item_id); - if (item) - { - if (item->getParentUUID() == mDstCatID) - { - LL_DEBUGS("Avatar") << "item " << item_id << " name " << item->getName() << " is already a child of " << mDstCatID << llendl; - return false; - } - LL_DEBUGS("Avatar") << "linking item " << item_id << " name " << item->getName() << " to " << mDstCatID << llendl; - // create an inventory item link. - if (ll_frand() < gSavedSettings.getF32("InventoryDebugSimulateOpFailureRate")) - { - LL_DEBUGS("Avatar") << "simulating failure by not sending request for item " << item_id << llendl; - return true; - } - link_inventory_item(gAgent.getID(), - item->getLinkedUUID(), - mDstCatID, - item->getName(), - item->getActualDescription(), - LLAssetType::AT_LINK, - new LLBoostFuncInventoryCallback( - boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,item_id,_1,LLTimer()))); - return true; - } - else - { - // create a base outfit link if appropriate. - LLViewerInventoryCategory *catp = gInventory.getCategory(item_id); - if (!catp) - { - llwarns << "link request failed, id not found as inventory item or category " << item_id << llendl; - return false; - } - const LLUUID cof = LLAppearanceMgr::instance().getCOF(); - std::string new_outfit_name = ""; - - LLAppearanceMgr::instance().purgeBaseOutfitLink(cof); - - if (catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) - { - if (ll_frand() < gSavedSettings.getF32("InventoryDebugSimulateOpFailureRate")) - { - LL_DEBUGS("Avatar") << "simulating failure by not sending request for item " << item_id << llendl; - return true; - } - LL_DEBUGS("Avatar") << "linking folder " << item_id << " name " << catp->getName() << " to cof " << cof << llendl; - link_inventory_item(gAgent.getID(), item_id, cof, catp->getName(), "", - LLAssetType::AT_LINK_FOLDER, - new LLBoostFuncInventoryCallback( - boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,item_id,_1,LLTimer()))); - new_outfit_name = catp->getName(); - request_sent = true; - } - - LLAppearanceMgr::instance().updatePanelOutfitName(new_outfit_name); - } - return request_sent; - } -}; - LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering, bool enforce_item_restrictions): mFireCount(0), @@ -533,6 +453,32 @@ void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item) mFireCount++; } +LLUpdateAppearanceAndEditWearableOnDestroy::LLUpdateAppearanceAndEditWearableOnDestroy(const LLUUID& item_id): + mItemID(item_id) +{ +} + +LLUpdateAppearanceAndEditWearableOnDestroy::~LLUpdateAppearanceAndEditWearableOnDestroy() +{ + LLAppearanceMgr::instance().updateAppearanceFromCOF(); + + // Start editing the item if previously requested. + gAgentWearables.editWearableIfRequested(mItemID); + + // TODO: camera mode may not be changed if a debug setting is tweaked + if( gAgentCamera.cameraCustomizeAvatar() ) + { + // If we're in appearance editing mode, the current tab may need to be refreshed + LLSidepanelAppearance *panel = dynamic_cast( + LLFloaterSidePanelContainer::getPanel("appearance")); + if (panel) + { + panel->showDefaultSubpart(); + } + } +} + + struct LLFoundData { LLFoundData() : @@ -1272,8 +1218,12 @@ void wear_on_avatar_cb(const LLUUID& inv_item, bool do_replace = false) } } -bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_update, bool replace, LLPointer cb) +bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, + bool do_update, + bool replace, + LLPointer cb) { + if (item_id_to_wear.isNull()) return false; // *TODO: issue with multi-wearable should be fixed: @@ -1320,7 +1270,11 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up { removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1)); } - addCOFItemLink(item_to_wear, do_update, cb); + if (!cb && do_update) + { + cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear); + } + addCOFItemLink(item_to_wear, cb); } break; case LLAssetType::AT_BODYPART: @@ -1329,8 +1283,11 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up // Remove the existing wearables of the same type. // Remove existing body parts anyway because we must not be able to wear e.g. two skins. removeCOFLinksOfType(item_to_wear->getWearableType()); - - addCOFItemLink(item_to_wear, do_update, cb); + if (!cb && do_update) + { + cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear); + } + addCOFItemLink(item_to_wear, cb); break; case LLAssetType::AT_OBJECT: rez_attachment(item_to_wear, NULL, replace); @@ -1640,7 +1597,7 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id) return items.size() > 0; } -void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category) +void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer cb) { LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; @@ -1656,7 +1613,7 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category) LLViewerInventoryCategory* catp = item->getLinkedCategory(); if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) { - gInventory.purgeObject(item->getUUID()); + remove_inventory_item(item->getUUID(), cb); } } } @@ -1843,7 +1800,7 @@ void LLAppearanceMgr::createBaseOutfitLink(const LLUUID& category, LLPointergetPreferredType() == LLFolderType::FT_OUTFIT) { @@ -2339,9 +2296,8 @@ bool areMatchingWearables(const LLViewerInventoryItem *a, const LLViewerInventor class LLDeferredCOFLinkObserver: public LLInventoryObserver { public: - LLDeferredCOFLinkObserver(const LLUUID& item_id, bool do_update, LLPointer cb = NULL, std::string description = ""): + LLDeferredCOFLinkObserver(const LLUUID& item_id, LLPointer cb = NULL, std::string description = ""): mItemID(item_id), - mDoUpdate(do_update), mCallback(cb), mDescription(description) { @@ -2357,14 +2313,13 @@ public: if (item) { gInventory.removeObserver(this); - LLAppearanceMgr::instance().addCOFItemLink(item,mDoUpdate,mCallback); + LLAppearanceMgr::instance().addCOFItemLink(item, mCallback); delete this; } } private: const LLUUID mItemID; - bool mDoUpdate; std::string mDescription; LLPointer mCallback; }; @@ -2372,42 +2327,26 @@ private: // BAP - note that this runs asynchronously if the item is not already loaded from inventory. // Dangerous if caller assumes link will exist after calling the function. -void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id, bool do_update, LLPointer cb, const std::string description) +void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id, + LLPointer cb, + const std::string description) { const LLInventoryItem *item = gInventory.getItem(item_id); if (!item) { - LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, do_update, cb, description); + LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, cb, description); gInventory.addObserver(observer); } else { - addCOFItemLink(item, do_update, cb, description); + addCOFItemLink(item, cb, description); } } -void modified_cof_cb(const LLUUID& inv_item) -{ - LLAppearanceMgr::instance().updateAppearanceFromCOF(); - - // Start editing the item if previously requested. - gAgentWearables.editWearableIfRequested(inv_item); - - // TODO: camera mode may not be changed if a debug setting is tweaked - if( gAgentCamera.cameraCustomizeAvatar() ) - { - // If we're in appearance editing mode, the current tab may need to be refreshed - LLSidepanelAppearance *panel = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance")); - if (panel) - { - panel->showDefaultSubpart(); - } - } -} - -void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update, LLPointer cb, const std::string description) +void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, + LLPointer cb, + const std::string description) { - std::string link_description = description; const LLViewerInventoryItem *vitem = dynamic_cast(item); if (!vitem) { @@ -2447,30 +2386,19 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update ++count; if (is_body_part && inv_item->getIsLinkType() && (vitem->getWearableType() == wearable_type)) { - gInventory.purgeObject(inv_item->getUUID()); + remove_inventory_item(inv_item->getUUID(), cb); } else if (count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) { // MULTI-WEARABLES: make sure we don't go over MAX_CLOTHING_PER_TYPE - gInventory.purgeObject(inv_item->getUUID()); + remove_inventory_item(inv_item->getUUID(), cb); } } } - if (linked_already) + if (!linked_already) { - if (do_update) - { - LLAppearanceMgr::updateAppearanceFromCOF(); - } - return; - } - else - { - if(do_update && cb.isNull()) - { - cb = new LLBoostFuncInventoryCallback(modified_cof_cb); - } + std::string link_description = description; if (vitem->getIsLinkType()) { link_description = vitem->getActualDescription(); @@ -2483,7 +2411,6 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update LLAssetType::AT_LINK, cb); } - return; } LLInventoryModel::item_array_t LLAppearanceMgr::findCOFItemLinks(const LLUUID& item_id) @@ -2567,7 +2494,7 @@ void LLAppearanceMgr::removeAllAttachmentsFromAvatar() removeItemsFromAvatar(ids_to_remove); } -void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id) +void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id, LLPointer cb) { gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); @@ -2582,12 +2509,12 @@ void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id) const LLInventoryItem* item = item_array.get(i).get(); if (item->getIsLinkType() && item->getLinkedUUID() == item_id) { - gInventory.purgeObject(item->getUUID()); + remove_inventory_item(item->getUUID(), cb); } } } -void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type) +void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type, LLPointer cb) { LLFindWearablesOfType filter_wearables_of_type(type); LLInventoryModel::cat_array_t cats; @@ -2600,7 +2527,7 @@ void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type) const LLViewerInventoryItem* item = *it; if (item->getIsLinkType()) // we must operate on links only { - gInventory.purgeObject(item->getUUID()); + remove_inventory_item(item->getUUID(), cb); } } } @@ -3550,7 +3477,7 @@ void LLAppearanceMgr::registerAttachment(const LLUUID& item_id) // we have to pass do_update = true to call LLAppearanceMgr::updateAppearanceFromCOF. // it will trigger gAgentWariables.notifyLoadingFinished() // But it is not acceptable solution. See EXT-7777 - LLAppearanceMgr::addCOFItemLink(item_id, false); // Add COF link for item. + LLAppearanceMgr::addCOFItemLink(item_id); // Add COF link for item. } else { @@ -3586,8 +3513,8 @@ bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id) gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), cats, items, - LLInventoryModel::EXCLUDE_TRASH, - find_links); + LLInventoryModel::EXCLUDE_TRASH, + find_links); return !items.empty(); } diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 0cc06ab210..2cc76c4b4c 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -107,12 +107,13 @@ public: const LLUUID getBaseOutfitUUID(); // Wear/attach an item (from a user's inventory) on the agent - bool wearItemOnAvatar(const LLUUID& item_to_wear, bool do_update = true, bool replace = false, LLPointer cb = NULL); + bool wearItemOnAvatar(const LLUUID& item_to_wear, bool do_update, bool replace = false, + LLPointer cb = NULL); // Update the displayed outfit name in UI. void updatePanelOutfitName(const std::string& name); - void purgeBaseOutfitLink(const LLUUID& category); + void purgeBaseOutfitLink(const LLUUID& category, LLPointer cb = NULL); void createBaseOutfitLink(const LLUUID& category, LLPointer link_waiter); void updateAgentWearables(LLWearableHoldingPattern* holder, bool append); @@ -136,15 +137,15 @@ public: LLPointer cb); // Add COF link to individual item. - void addCOFItemLink(const LLUUID& item_id, bool do_update = true, LLPointer cb = NULL, const std::string description = ""); - void addCOFItemLink(const LLInventoryItem *item, bool do_update = true, LLPointer cb = NULL, const std::string description = ""); + void addCOFItemLink(const LLUUID& item_id, LLPointer cb = NULL, const std::string description = ""); + void addCOFItemLink(const LLInventoryItem *item, LLPointer cb = NULL, const std::string description = ""); // Find COF entries referencing the given item. LLInventoryModel::item_array_t findCOFItemLinks(const LLUUID& item_id); // Remove COF entries - void removeCOFItemLinks(const LLUUID& item_id); - void removeCOFLinksOfType(LLWearableType::EType type); + void removeCOFItemLinks(const LLUUID& item_id, LLPointer cb = NULL); + void removeCOFLinksOfType(LLWearableType::EType type, LLPointer cb = NULL); void removeAllClothesFromAvatar(); void removeAllAttachmentsFromAvatar(); @@ -272,6 +273,20 @@ private: bool mEnforceItemRestrictions; }; +class LLUpdateAppearanceAndEditWearableOnDestroy: public LLInventoryCallback +{ +public: + LLUpdateAppearanceAndEditWearableOnDestroy(const LLUUID& item_id); + + /* virtual */ void fire(const LLUUID& item_id) {} + + ~LLUpdateAppearanceAndEditWearableOnDestroy(); + +private: + LLUUID mItemID; +}; + +class #define SUPPORT_ENSEMBLES 0 diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index 56051ff684..def4d40f9f 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -619,7 +619,7 @@ void LLFloaterGesture::addToCurrentOutFit() LLAppearanceMgr* am = LLAppearanceMgr::getInstance(); for(uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); it++) { - am->addCOFItemLink(*it); + am->addCOFItemLink(*it, new LLUpdateAppearanceAndEditWearableOnDestroy(*it)); } } diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index c09d4393c8..0e3057dcad 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -1184,12 +1184,12 @@ BOOL LLPanelOutfitEdit::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, * second argument is used to delay the appearance update until all dragged items * are added to optimize user experience. */ - LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), false); + LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID()); } else { // if asset id is not available for the item we must wear it immediately (attachments only) - LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), true); + LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), new LLUpdateAppearanceAndEditWearableOnDestroy(item->getUUID())); } } diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 7cb62efb47..6b0e8ed4ef 100755 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -274,7 +274,7 @@ class LLBoostFuncInventoryCallback: public LLInventoryCallback { public: - LLBoostFuncInventoryCallback(inventory_func_type fire_func, + LLBoostFuncInventoryCallback(inventory_func_type fire_func = no_op_inventory_func, nullary_func_type destroy_func = no_op): mFireFunc(fire_func), mDestroyFunc(destroy_func) -- 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/llappearancemgr.cpp | 61 +++++++++----------------------------- indra/newview/llinventorymodel.cpp | 59 ++++++++++++++++++++++++++++++------ indra/newview/llinventorymodel.h | 3 ++ 3 files changed, 67 insertions(+), 56 deletions(-) mode change 100644 => 100755 indra/newview/llinventorymodel.h (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 634f5d1389..5a9901f12d 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1541,15 +1541,8 @@ bool LLAppearanceMgr::getCanRemoveOutfit(const LLUUID& outfit_cat_id) // static bool LLAppearanceMgr::getCanRemoveFromCOF(const LLUUID& outfit_cat_id) { - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; LLFindWearablesEx is_worn(/*is_worn=*/ true, /*include_body_parts=*/ false); - gInventory.collectDescendentsIf(outfit_cat_id, - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - is_worn); - return items.size() > 0; + return gInventory.hasMatchingDirectDescendent(outfit_cat_id, is_worn); } // static @@ -1560,15 +1553,8 @@ bool LLAppearanceMgr::getCanAddToCOF(const LLUUID& outfit_cat_id) return false; } - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false); - gInventory.collectDescendentsIf(outfit_cat_id, - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - not_worn); - return items.size() > 0; + return gInventory.hasMatchingDirectDescendent(outfit_cat_id, not_worn); } bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id) @@ -1586,15 +1572,8 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id) } // Check whether the outfit contains any wearables we aren't wearing already (STORM-702). - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; LLFindWearablesEx is_worn(/*is_worn=*/ false, /*include_body_parts=*/ true); - gInventory.collectDescendentsIf(outfit_cat_id, - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - is_worn); - return items.size() > 0; + return gInventory.hasMatchingDirectDescendent(outfit_cat_id, is_worn); } void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer cb) @@ -2243,6 +2222,7 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego LLAppearanceMgr::changeOutfit(TRUE, category->getUUID(), append); } +// FIXME do we really want to search entire inventory for matching name? void LLAppearanceMgr::wearOutfitByName(const std::string& name) { LL_INFOS("Avatar") << self_av_string() << "Wearing category " << name << LL_ENDL; @@ -3501,22 +3481,21 @@ void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id) BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const { - return gInventory.isObjectDescendentOf(obj_id, getCOF()); + const LLUUID& cof = getCOF(); + if (obj_id == cof) + return TRUE; + const LLInventoryObject* obj = gInventory.getObject(obj_id); + if (obj && obj->getParentUUID() == cof) + return TRUE; + return FALSE; } // static bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id) { - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLLinkedItemIDMatches find_links(gInventory.getLinkedItemID(obj_id)); - gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - find_links); - - return !items.empty(); + const LLUUID& target_id = gInventory.getLinkedItemID(obj_id); + LLLinkedItemIDMatches find_links(target_id); + return gInventory.hasMatchingDirectDescendent(LLAppearanceMgr::instance().getCOF(), find_links); } BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const @@ -3533,18 +3512,6 @@ BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const // For now, don't allow direct deletion from the COF. Instead, force users // to choose "Detach" or "Take Off". return TRUE; - /* - const LLInventoryObject *obj = gInventory.getObject(obj_id); - if (!obj) return FALSE; - - // Can't delete bodyparts, since this would be equivalent to removing the item. - if (obj->getType() == LLAssetType::AT_BODYPART) return TRUE; - - // Can't delete the folder link, since this is saved for bookkeeping. - if (obj->getActualType() == LLAssetType::AT_LINK_FOLDER) return TRUE; - - return FALSE; - */ } class CallAfterCategoryFetchStage2: public LLInventoryFetchItemsObserver 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 diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h old mode 100644 new mode 100755 index 0b017b7514..50b57ea08d --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -205,6 +205,9 @@ public: EXCLUDE_TRASH = FALSE, INCLUDE_TRASH = TRUE }; + // Simpler existence test if matches don't actually need to be collected. + bool hasMatchingDirectDescendent(const LLUUID& cat_id, + LLInventoryCollectFunctor& filter); void collectDescendents(const LLUUID& id, cat_array_t& categories, item_array_t& items, -- cgit v1.2.3 From a9fa707a7da9977914db8527f15b59bb6a4bc6b7 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 24 Apr 2013 16:09:33 -0400 Subject: SH-4128 - more cleanup of COF-link manipulating functions --- indra/newview/llappearancemgr.cpp | 60 +++++++++++++++++++------------------- indra/newview/llfloatergesture.cpp | 3 +- 2 files changed, 32 insertions(+), 31 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 5a9901f12d..792220c385 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -430,6 +430,16 @@ LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit selfStartPhase("update_appearance_on_destroy"); } +void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item) +{ + LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(inv_item); + const std::string item_name = item ? item->getName() : "ITEM NOT FOUND"; +#ifndef LL_RELEASE_FOR_DOWNLOAD + LL_DEBUGS("Avatar") << self_av_string() << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << LL_ENDL; +#endif + mFireCount++; +} + LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy() { if (!LLApp::isExiting()) @@ -443,16 +453,6 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy() } } -void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item) -{ - LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(inv_item); - const std::string item_name = item ? item->getName() : "ITEM NOT FOUND"; -#ifndef LL_RELEASE_FOR_DOWNLOAD - LL_DEBUGS("Avatar") << self_av_string() << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << LL_ENDL; -#endif - mFireCount++; -} - LLUpdateAppearanceAndEditWearableOnDestroy::LLUpdateAppearanceAndEditWearableOnDestroy(const LLUUID& item_id): mItemID(item_id) { @@ -460,20 +460,23 @@ LLUpdateAppearanceAndEditWearableOnDestroy::LLUpdateAppearanceAndEditWearableOnD LLUpdateAppearanceAndEditWearableOnDestroy::~LLUpdateAppearanceAndEditWearableOnDestroy() { - LLAppearanceMgr::instance().updateAppearanceFromCOF(); - - // Start editing the item if previously requested. - gAgentWearables.editWearableIfRequested(mItemID); - - // TODO: camera mode may not be changed if a debug setting is tweaked - if( gAgentCamera.cameraCustomizeAvatar() ) + if (!LLApp::isExiting()) { - // If we're in appearance editing mode, the current tab may need to be refreshed - LLSidepanelAppearance *panel = dynamic_cast( - LLFloaterSidePanelContainer::getPanel("appearance")); - if (panel) + LLAppearanceMgr::instance().updateAppearanceFromCOF(); + + // Start editing the item if previously requested. + gAgentWearables.editWearableIfRequested(mItemID); + + // TODO: camera mode may not be changed if a debug setting is tweaked + if( gAgentCamera.cameraCustomizeAvatar() ) { - panel->showDefaultSubpart(); + // If we're in appearance editing mode, the current tab may need to be refreshed + LLSidepanelAppearance *panel = dynamic_cast( + LLFloaterSidePanelContainer::getPanel("appearance")); + if (panel) + { + panel->showDefaultSubpart(); + } } } } @@ -1587,13 +1590,10 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointergetActualType() != LLAssetType::AT_LINK_FOLDER) continue; - if (item->getIsLinkType()) + LLViewerInventoryCategory* catp = item->getLinkedCategory(); + if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) { - LLViewerInventoryCategory* catp = item->getLinkedCategory(); - if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) - { - remove_inventory_item(item->getUUID(), cb); - } + remove_inventory_item(item->getUUID(), cb); } } } @@ -2276,7 +2276,7 @@ bool areMatchingWearables(const LLViewerInventoryItem *a, const LLViewerInventor class LLDeferredCOFLinkObserver: public LLInventoryObserver { public: - LLDeferredCOFLinkObserver(const LLUUID& item_id, LLPointer cb = NULL, std::string description = ""): + LLDeferredCOFLinkObserver(const LLUUID& item_id, LLPointer cb, const std::string& description): mItemID(item_id), mCallback(cb), mDescription(description) @@ -2293,7 +2293,7 @@ public: if (item) { gInventory.removeObserver(this); - LLAppearanceMgr::instance().addCOFItemLink(item, mCallback); + LLAppearanceMgr::instance().addCOFItemLink(item, mCallback, mDescription); delete this; } } diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index def4d40f9f..af5c11e12c 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -617,9 +617,10 @@ void LLFloaterGesture::addToCurrentOutFit() uuid_vec_t ids; getSelectedIds(ids); LLAppearanceMgr* am = LLAppearanceMgr::getInstance(); + LLPointer cb = new LLUpdateAppearanceOnDestroy; for(uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); it++) { - am->addCOFItemLink(*it, new LLUpdateAppearanceAndEditWearableOnDestroy(*it)); + am->addCOFItemLink(*it, cb); } } -- 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/llappearancemgr.cpp | 24 ++++++++++++++---------- indra/newview/llgesturemgr.cpp | 13 ++++++++++--- indra/newview/llinventorymodel.cpp | 5 +++-- indra/newview/llpaneleditwearable.cpp | 23 ++++++++++++++++++----- 4 files changed, 45 insertions(+), 20 deletions(-) mode change 100644 => 100755 indra/newview/llgesturemgr.cpp mode change 100644 => 100755 indra/newview/llpaneleditwearable.cpp (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 792220c385..399cea676c 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1265,18 +1265,21 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, switch (item_to_wear->getType()) { case LLAssetType::AT_CLOTHING: - if (gAgentWearables.areWearablesLoaded()) + if (gAgentWearables.areWearablesLoaded()) { + if (!cb && do_update) + { + cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear); + } S32 wearable_count = gAgentWearables.getWearableCount(item_to_wear->getWearableType()); if ((replace && wearable_count != 0) || (wearable_count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) ) { - removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1)); - } - if (!cb && do_update) - { - cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear); + LLUUID item_id = gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), + wearable_count-1); + removeCOFItemLinks(item_id, cb); } + addCOFItemLink(item_to_wear, cb); } break; @@ -3284,21 +3287,22 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove) if (ids_to_remove.empty()) { llwarns << "called with empty list, nothing to do" << llendl; + return; } + LLPointer cb = new LLUpdateAppearanceOnDestroy; for (uuid_vec_t::const_iterator it = ids_to_remove.begin(); it != ids_to_remove.end(); ++it) { const LLUUID& id_to_remove = *it; const LLUUID& linked_item_id = gInventory.getLinkedItemID(id_to_remove); - removeCOFItemLinks(linked_item_id); + removeCOFItemLinks(linked_item_id, cb); } - updateAppearanceFromCOF(); } void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove) { LLUUID linked_item_id = gInventory.getLinkedItemID(id_to_remove); - removeCOFItemLinks(linked_item_id); - updateAppearanceFromCOF(); + LLPointer cb = new LLUpdateAppearanceOnDestroy; + removeCOFItemLinks(linked_item_id, cb); } bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_body) diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp old mode 100644 new mode 100755 index 9aa86297fc..5eaa83d872 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -299,6 +299,12 @@ void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id, } +void notify_update_label(const LLUUID& base_item_id) +{ + gInventory.addChangedMask(LLInventoryObserver::LABEL, base_item_id); + LLGestureMgr::instance().notifyObservers(); +} + void LLGestureMgr::deactivateGesture(const LLUUID& item_id) { const LLUUID& base_item_id = get_linked_uuid(item_id); @@ -322,7 +328,6 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id) } mActive.erase(it); - gInventory.addChangedMask(LLInventoryObserver::LABEL, base_item_id); // Inform the database of this change LLMessageSystem* msg = gMessageSystem; @@ -338,9 +343,11 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id) gAgent.sendReliableMessage(); - LLAppearanceMgr::instance().removeCOFItemLinks(base_item_id); + LLPointer cb = + new LLBoostFuncInventoryCallback(no_op_inventory_func, + boost::bind(notify_update_label,base_item_id)); - notifyObservers(); + LLAppearanceMgr::instance().removeCOFItemLinks(base_item_id, cb); } 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(); diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp old mode 100644 new mode 100755 index e71dba5cae..06c923273b --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1079,10 +1079,15 @@ void LLPanelEditWearable::saveChanges(bool force_save_as) if (force_save_as) { - // the name of the wearable has changed, re-save wearable with new name - LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID()); + // FIXME race condition if removeCOFItemLinks does not + // complete immediately. Looks like we're counting on the + // fact that updateAppearanceFromCOF will get called after + // we exit customize mode. + + // the name of the wearable has changed, re-save wearable with new name + LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID()); gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, description, FALSE); - mNameEditor->setText(mWearableItem->getName()); + mNameEditor->setText(mWearableItem->getName()); } else { @@ -1091,6 +1096,14 @@ void LLPanelEditWearable::saveChanges(bool force_save_as) // version so texture baking service knows appearance has changed. if (link_item) { + // FIXME - two link-modifying calls here plus one + // inventory change request, none of which use a + // callback. When does a new appearance request go out + // and how is it synced with these changes? As above, + // we seem to be implicitly depending on + // updateAppearanceFromCOF() to be called when we + // exit customize mode. + // Create new link link_inventory_item( gAgent.getID(), link_item->getLinkedUUID(), @@ -1100,9 +1113,9 @@ void LLPanelEditWearable::saveChanges(bool force_save_as) LLAssetType::AT_LINK, NULL); // Remove old link - gInventory.purgeObject(link_item->getUUID()); + remove_inventory_item(link_item->getUUID()); } - gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name); + gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name); } -- 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 ++-- indra/newview/llpaneleditwearable.cpp | 2 +- indra/newview/llviewerinventory.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/newview') 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); diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 06c923273b..580e31591c 100755 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1113,7 +1113,7 @@ void LLPanelEditWearable::saveChanges(bool force_save_as) LLAssetType::AT_LINK, NULL); // Remove old link - remove_inventory_item(link_item->getUUID()); + remove_inventory_item(link_item->getUUID(), NULL); } gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name); } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 316fca7769..06efeb86d9 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1276,7 +1276,7 @@ void remove_inventory_item( } else { - llwarns << "remove_inventory_item called for nonexistent item " << item_id << llendl; + llwarns << "remove_inventory_item called for invalid or nonexistent item " << item_id << llendl; } } -- cgit v1.2.3 From d58b9ee54e84b709e063cdbbc349de25feafa59b Mon Sep 17 00:00:00 2001 From: Nyx Linden Date: Thu, 25 Apr 2013 14:09:42 -0400 Subject: SH-4050 FIX camera goes underground if hover set low enough Changing viewer limit for avatar height to match server limit, camera does not go underground. Also clarified where we do not need avatar offset in the code, through comments --- indra/newview/llvoavatar.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 0475e9fc89..bf6e28b93d 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2144,7 +2144,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) { LLVector3 tagPos = mRoot->getWorldPosition(); tagPos[VZ] -= mPelvisToFoot; - tagPos[VZ] += ( mBodySize[VZ] + 0.125f ); + tagPos[VZ] += ( mBodySize[VZ] + 0.125f ); // does not need mAvatarOffset -Nyx mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos ); } }//if ( voiceEnabled ) @@ -2885,6 +2885,8 @@ void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) local_camera_up.normalize(); local_camera_up = local_camera_up * inv_root_rot; + + // position is based on head position, does not require mAvatarOffset here. - Nyx LLVector3 avatar_ellipsoid(mBodySize.mV[VX] * 0.4f, mBodySize.mV[VY] * 0.4f, mBodySize.mV[VZ] * NAMETAG_VERT_OFFSET_WEIGHT); -- 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/llinventorybridge.cpp | 9 +- indra/newview/llinventorymodel.cpp | 207 ++++++++++---------------- indra/newview/llinventorymodel.h | 19 +-- indra/newview/llpreview.cpp | 7 - indra/newview/llviewerinventory.cpp | 286 ++++++++++++++++++++++++++++-------- indra/newview/llviewerinventory.h | 14 +- 6 files changed, 321 insertions(+), 221 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index a5043a30ac..27f35c5946 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1159,17 +1159,10 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid) { - LLInventoryCategory* cat = model->getCategory(uuid); - if (cat) - { - model->purgeDescendentsOf(uuid); - model->notifyObservers(); - } LLInventoryObject* obj = model->getObject(uuid); if (obj) { - model->purgeObject(uuid); - model->notifyObservers(); + remove_inventory_object(uuid, NULL); } } 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); } } diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 50b57ea08d..b7e1888f20 100755 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -325,6 +325,14 @@ public: // Delete //-------------------------------------------------------------------- public: + + // Update model after an item is confirmed as removed from + // server. Works for categories or items. + void onObjectDeletedFromServer(const LLUUID& item_id); + + // Update model after all descendents removed from server. + void onDescendentsPurgedFromServer(const LLUUID& object_id); + // Delete a particular inventory object by ID. Will purge one // object from the internal data structures, maintaining a // consistent internal state. No cache accounting, observer @@ -337,17 +345,6 @@ public: /// removeItem() or removeCategory(), whichever is appropriate void removeObject(const LLUUID& object_id); - // Delete a particular inventory object by ID, and delete it from - // the server. Also updates linked items. - void purgeObject(const LLUUID& id); - - // Collects and purges the descendants of the id - // provided. If the category is not found, no action is - // taken. This method goes through the long winded process of - // removing server representation of folders and items while doing - // cache accounting in a fairly efficient manner. This method does - // not notify observers (though maybe it should...) - void purgeDescendentsOf(const LLUUID& id); protected: void updateLinkedObjectsFromPurge(const LLUUID& baseobj_id); diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp index 04934b13f1..452efad291 100644 --- a/indra/newview/llpreview.cpp +++ b/indra/newview/llpreview.cpp @@ -401,13 +401,6 @@ void LLPreview::onDiscardBtn(void* data) self->mForceClose = TRUE; self->closeFloater(); - // Delete the item entirely - /* - item->removeFromServer(); - gInventory.deleteObject(item->getUUID()); - gInventory.notifyObservers(); - */ - // Move the item to the trash const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if (item->getParentUUID() != trash_id) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 06efeb86d9..fbd6b292bd 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -65,6 +65,7 @@ #include "llavataractions.h" #include "lllogininstance.h" #include "llfavoritesbar.h" +#include "llclipboard.h" // Two do-nothing ops for use in callbacks. void no_op_inventory_func(const LLUUID&) {} @@ -345,24 +346,6 @@ void LLViewerInventoryItem::cloneViewerItem(LLPointer& ne } } -void LLViewerInventoryItem::removeFromServer() -{ - lldebugs << "Removing inventory item " << mUUID << " from server." - << llendl; - - LLInventoryModel::LLCategoryUpdate up(mParentUUID, -1); - gInventory.accountForUpdate(up); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RemoveInventoryItem); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_ItemID, mUUID); - gAgent.sendReliableMessage(); -} - void LLViewerInventoryItem::updateServer(BOOL is_new) const { if(!mIsComplete) @@ -637,30 +620,6 @@ void LLViewerInventoryCategory::updateServer(BOOL is_new) const gAgent.sendReliableMessage(); } -void LLViewerInventoryCategory::removeFromServer( void ) -{ - llinfos << "Removing inventory category " << mUUID << " from server." - << llendl; - // communicate that change with the server. - if(LLFolderType::lookupIsProtectedType(mPreferredType)) - { - LLNotificationsUtil::add("CannotRemoveProtectedCategories"); - return; - } - - LLInventoryModel::LLCategoryUpdate up(mParentUUID, -1); - gInventory.accountForUpdate(up); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RemoveInventoryFolder); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_FolderData); - msg->addUUIDFast(_PREHASH_FolderID, mUUID); - gAgent.sendReliableMessage(); -} - S32 LLViewerInventoryCategory::getVersion() const { return mVersion; @@ -1179,25 +1138,10 @@ void move_inventory_item( gAgent.sendReliableMessage(); } -void handle_item_deletion(const LLUUID& item_id) -{ - LLPointer obj = gInventory.getItem(item_id); - if(obj) - { - // From item removeFromServer() - LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1); - gInventory.accountForUpdate(up); - - // From purgeObject() - LLPreview::hide(item_id); - gInventory.deleteObject(item_id); - } -} - -class RemoveItemResponder: public LLHTTPClient::Responder +class RemoveObjectResponder: public LLHTTPClient::Responder { public: - RemoveItemResponder(const LLUUID& item_id, LLPointer callback): + RemoveObjectResponder(const LLUUID& item_id, LLPointer callback): mItemUUID(item_id), mCallback(callback) { @@ -1212,7 +1156,7 @@ public: } llinfos << "succeeded: " << ll_pretty_print_sd(content) << llendl; - handle_item_deletion(mItemUUID); + gInventory.onObjectDeletedFromServer(mItemUUID); if (mCallback) { @@ -1251,7 +1195,7 @@ void remove_inventory_item( { std::string url = cap + std::string("/item/") + item_id.asString(); llinfos << "url: " << url << llendl; - LLCurl::ResponderPtr responder_ptr = new RemoveItemResponder(item_id,cb); + LLCurl::ResponderPtr responder_ptr = new RemoveObjectResponder(item_id,cb); LLHTTPClient::del(url,responder_ptr); } else // no cap @@ -1267,7 +1211,7 @@ void remove_inventory_item( // Update inventory and call callback immediately since // message-based system has no callback mechanism (!) - handle_item_deletion(item_id); + gInventory.onObjectDeletedFromServer(item_id); if (cb) { cb->fire(item_id); @@ -1280,6 +1224,224 @@ void remove_inventory_item( } } +class LLRemoveObjectOnDestroy: public LLInventoryCallback +{ +public: + LLRemoveObjectOnDestroy(const LLUUID& item_id, LLPointer cb): + mID(item_id), + mCB(cb) + { + } + /* virtual */ void fire(const LLUUID& item_id) {} + ~LLRemoveObjectOnDestroy() + { + remove_inventory_object(mID, mCB); + } +private: + LLUUID mID; + LLPointer mCB; +}; + +void remove_inventory_category( + const LLUUID& cat_id, + LLPointer cb) +{ + llinfos << "cat_id: [" << cat_id << "] " << llendl; + LLPointer obj = gInventory.getCategory(cat_id); + if(obj) + { + if(LLFolderType::lookupIsProtectedType(obj->getPreferredType())) + { + LLNotificationsUtil::add("CannotRemoveProtectedCategories"); + return; + } + LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(cat_id); + if(children != LLInventoryModel::CHILDREN_NO) + { + llinfos << "Will purge descendents first before deleting category " << cat_id << llendl; + LLPointer wrap_cb = new LLRemoveObjectOnDestroy(cat_id,cb); + purge_descendents_of(cat_id, wrap_cb); + return; + } + + std::string cap; + if (gAgent.getRegion()) + { + cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); + } + if (!cap.empty()) + { + std::string url = cap + std::string("/category/") + cat_id.asString(); + llinfos << "url: " << url << llendl; + LLCurl::ResponderPtr responder_ptr = new RemoveObjectResponder(cat_id,cb); + LLHTTPClient::del(url,responder_ptr); + } + else // no cap + { + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RemoveInventoryFolder); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_FolderData); + msg->addUUIDFast(_PREHASH_FolderID, cat_id); + gAgent.sendReliableMessage(); + + // Update inventory and call callback immediately since + // message-based system has no callback mechanism (!) + gInventory.onObjectDeletedFromServer(cat_id); + if (cb) + { + cb->fire(cat_id); + } + } + } + else + { + llwarns << "remove_inventory_category called for invalid or nonexistent item " << cat_id << llendl; + } +} + +void remove_inventory_object( + const LLUUID& object_id, + LLPointer cb) +{ + if (gInventory.getCategory(object_id)) + { + remove_inventory_category(object_id, cb); + } + else + { + remove_inventory_item(object_id, cb); + } +} + +class PurgeDescendentsResponder: public LLHTTPClient::Responder +{ +public: + PurgeDescendentsResponder(const LLUUID& item_id, LLPointer callback): + mItemUUID(item_id), + mCallback(callback) + { + } + /* virtual */ void httpSuccess() + { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + llinfos << "succeeded: " << ll_pretty_print_sd(content) << llendl; + + gInventory.onDescendentsPurgedFromServer(mItemUUID); + + if (mCallback) + { + mCallback->fire(mItemUUID); + } + } + /*virtual*/ void httpFailure() + { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << llendl; + } +private: + LLPointer mCallback; + const LLUUID mItemUUID; +}; + +// 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 purge_descendents_of(const LLUUID& id, LLPointer cb) +{ + LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(id); + if(children == LLInventoryModel::CHILDREN_NO) + { + llinfos << "No descendents to purge for " << id << llendl; + return; + } + LLPointer cat = gInventory.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 << "purge_descendents_of clipboard case " << cat->getName() + << " iterate and purge non hidden items" << llendl; + LLInventoryModel::cat_array_t* categories; + LLInventoryModel::item_array_t* items; + // Get the list of direct descendants in tha categoy passed as argument + gInventory.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 (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); it != categories->end(); ++it) + { + list_uuids.push_back((*it)->getUUID()); + } + for (LLInventoryModel::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)) + { + remove_inventory_object(*it, NULL); + } + } + } + else + { + std::string cap; + if (gAgent.getRegion()) + { + cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); + } + if (!cap.empty()) + { + std::string url = cap + std::string("/category/") + id.asString() + "/children"; + llinfos << "url: " << url << llendl; + LLCurl::ResponderPtr responder_ptr = new PurgeDescendentsResponder(id,cb); + LLHTTPClient::del(url,responder_ptr); + } + else // no cap + { + // Fast purge + llinfos << "purge_descendents_of fast case " << cat->getName() << llendl; + + // 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(); + + // Update model immediately because there is no callback mechanism. + gInventory.onDescendentsPurgedFromServer(id); + if (cb) + { + cb->fire(id); + } + } + } + } +} + const LLUUID get_folder_by_itemtype(const LLInventoryItem *src) { LLUUID retval = LLUUID::null; diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 6b0e8ed4ef..4e24dc87d1 100755 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -118,7 +118,6 @@ public: void cloneViewerItem(LLPointer& newitem) const; // virtual methods - virtual void removeFromServer( void ); virtual void updateParentOnServer(BOOL restamp) const; virtual void updateServer(BOOL is_new) const; void fetchFromServer(void) const; @@ -198,7 +197,6 @@ public: LLViewerInventoryCategory(const LLViewerInventoryCategory* other); void copyViewerCategory(const LLViewerInventoryCategory* other); - virtual void removeFromServer(); virtual void updateParentOnServer(BOOL restamp_children) const; virtual void updateServer(BOOL is_new) const; @@ -369,6 +367,18 @@ void remove_inventory_item( const LLUUID& item_id, LLPointer cb); +void remove_inventory_category( + const LLUUID& cat_id, + LLPointer cb); + +void remove_inventory_object( + const LLUUID& object_id, + LLPointer cb); + +void purge_descendents_of( + const LLUUID& cat_id, + LLPointer cb); + const LLUUID get_folder_by_itemtype(const LLInventoryItem *src); void copy_inventory_from_notecard(const LLUUID& destination_id, -- cgit v1.2.3 From 638514ca0cbc666a324e757c8de4cceaaaeeadd4 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 26 Apr 2013 10:01:09 -0400 Subject: SH-4142 FIX - avoid stack overflow in an AISv3 responder failure case. --- indra/newview/llviewerinventory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index fbd6b292bd..c44552d7d2 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1168,7 +1168,7 @@ public: const LLSD& content = getContent(); if (!content.isMap()) { - failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + llwarns << "Malformed response contents" << content << llendl; return; } llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << llendl; @@ -1347,7 +1347,7 @@ public: const LLSD& content = getContent(); if (!content.isMap()) { - failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + llwarns << "Malformed response contents" << content << llendl; return; } llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << llendl; -- cgit v1.2.3 From fb51bab6cd2e3f037142ce7c5f547113d76f0504 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 26 Apr 2013 10:17:41 -0400 Subject: SH-4142 FIX - made error messages a bit more informative --- indra/newview/llviewerinventory.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index c44552d7d2..3eab85b8b3 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1166,12 +1166,14 @@ public: /*virtual*/ void httpFailure() { const LLSD& content = getContent(); + S32 status = getStatus(); + const std::string& reason = getReason(); if (!content.isMap()) { - llwarns << "Malformed response contents" << content << llendl; + llwarns << "Malformed response contents " << content << " id " << mItemUUID << " status " << status << " reason " << reason << llendl; return; } - llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << llendl; + llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << " status " << status << " reason " << reason << llendl; } private: LLPointer mCallback; @@ -1345,12 +1347,14 @@ public: /*virtual*/ void httpFailure() { const LLSD& content = getContent(); + S32 status = getStatus(); + const std::string& reason = getReason(); if (!content.isMap()) { - llwarns << "Malformed response contents" << content << llendl; + llwarns << "Malformed response contents " << content << " id " << mItemUUID << " status " << status << " reason " << reason << llendl; return; } - llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << llendl; + llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << " status " << status << " reason " << reason << llendl; } private: LLPointer mCallback; -- cgit v1.2.3 From e4c96827d237a489873ce8453640d3a13f83d01a Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 29 Apr 2013 14:24:05 -0400 Subject: SH-4144 FIX - Debug setting now disables use of AISv3 by default. This is just a workaround for the problem of aditi advertising the cap when it isn't really present. Once we have aditi in a consistent state we should remove the setting, or at least default it to true. --- indra/newview/app_settings/logcontrol.xml | 2 +- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llviewerinventory.cpp | 10 +++++++--- 3 files changed, 19 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 92a241857e..c5561166fc 100755 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -42,8 +42,8 @@ tags - diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 18a33b3542..1262089b3d 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -14033,6 +14033,17 @@ Value 1 + UseAISv3Inventory + + Comment + Allow use of AISv3 inventory - this setting should only be needed during development. + Persist + 1 + Type + Boolean + Value + 0 + ClickToWalk Comment diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 3eab85b8b3..d45512df9c 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -627,6 +627,10 @@ S32 LLViewerInventoryCategory::getVersion() const void LLViewerInventoryCategory::setVersion(S32 version) { + if (mPreferredType == LLFolderType::FT_CURRENT_OUTFIT) + { + llinfos << "cof version change " << mVersion << " => " << version << llendl; + } mVersion = version; } @@ -1189,7 +1193,7 @@ void remove_inventory_item( if(obj) { std::string cap; - if (gAgent.getRegion()) + if (gAgent.getRegion() && gSavedSettings.getBOOL("UseAISv3Inventory")) { cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); } @@ -1267,7 +1271,7 @@ void remove_inventory_category( } std::string cap; - if (gAgent.getRegion()) + if (gAgent.getRegion() && gSavedSettings.getBOOL("UseAISv3Inventory")) { cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); } @@ -1409,7 +1413,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer cb) else { std::string cap; - if (gAgent.getRegion()) + if (gAgent.getRegion() && gSavedSettings.getBOOL("UseAISv3Inventory")) { cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); } -- cgit v1.2.3 From 72aa727a3f371cf592d33e6cccefbf74be053b70 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 29 Apr 2013 14:29:04 -0400 Subject: removed overly enthusiastic log setting --- indra/newview/app_settings/logcontrol.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index c5561166fc..92a241857e 100755 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -42,8 +42,8 @@ tags - Avatar -- cgit v1.2.3 From 9caeb5ad5045352c4bb77195c5c0bc71575bc3fd Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 29 Apr 2013 14:31:15 -0400 Subject: removed debugging code that got pushed incorrectly. --- indra/newview/app_settings/logcontrol.xml | 2 +- indra/newview/llviewerinventory.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 92a241857e..c5561166fc 100755 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -42,8 +42,8 @@ tags - diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d45512df9c..b39dbd51a1 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -627,10 +627,12 @@ S32 LLViewerInventoryCategory::getVersion() const void LLViewerInventoryCategory::setVersion(S32 version) { +#if 0 if (mPreferredType == LLFolderType::FT_CURRENT_OUTFIT) { llinfos << "cof version change " << mVersion << " => " << version << llendl; } +#endif mVersion = version; } -- cgit v1.2.3 From 48d684c7befae1ca7f7b43f682d7bea03fc4e0c0 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 29 Apr 2013 14:32:03 -0400 Subject: logcontrol.xml fix this time for sure. --- indra/newview/app_settings/logcontrol.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index c5561166fc..92a241857e 100755 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -42,8 +42,8 @@ tags - Avatar -- cgit v1.2.3 From ae53d22141288ab1b5ba4a5927d11cf84c59d445 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 29 Apr 2013 16:59:10 -0400 Subject: SH-4140 FIX, SH-3860 FIX - appearance on first-time login should now be reliable without depending on retries of appearance update requests. May still see COF mismatch errors in the log - these will only be fixed, if at all, with AISv3 integration. --- indra/newview/llappearancemgr.cpp | 13 ++++++++++--- indra/newview/llviewerinventory.cpp | 2 -- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 399cea676c..40ec88f1be 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2890,7 +2890,7 @@ protected: } if (content["success"].asBoolean()) { - LL_DEBUGS("Avatar") << dumpResponse() << LL_ENDL; + //LL_DEBUGS("Avatar") << dumpResponse() << LL_ENDL; if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) { dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_ok", content); @@ -2907,7 +2907,8 @@ protected: { const LLSD& content = getContent(); LL_WARNS("Avatar") << "appearance update request failed " - << dumpResponse() << LL_ENDL; + << dumpResponse() << LL_ENDL; + if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) { dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_error", content); @@ -3247,6 +3248,13 @@ void show_created_outfit(LLUUID& folder_id, bool show_panel = true) LLAppearanceMgr::getInstance()->updateIsDirty(); gAgentWearables.notifyLoadingFinished(); // New outfit is saved. LLAppearanceMgr::getInstance()->updatePanelOutfitName(""); + + // For SSB, need to update appearance after we add a base outfit + // link, since, the COF version has changed. There is a race + // condition in initial outfit setup which can lead to rez + // failures - SH-3860. + LLPointer cb = new LLUpdateAppearanceOnDestroy; + LLAppearanceMgr::getInstance()->createBaseOutfitLink(folder_id, cb); } LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel) @@ -3267,7 +3275,6 @@ LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, b LLPointer cb = new LLBoostFuncInventoryCallback(no_op_inventory_func, boost::bind(show_created_outfit,folder_id,show_panel)); shallowCopyCategoryContents(getCOF(),folder_id, cb); - createBaseOutfitLink(folder_id, cb); dumpCat(folder_id,"COF, new outfit"); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index b39dbd51a1..d45512df9c 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -627,12 +627,10 @@ S32 LLViewerInventoryCategory::getVersion() const void LLViewerInventoryCategory::setVersion(S32 version) { -#if 0 if (mPreferredType == LLFolderType::FT_CURRENT_OUTFIT) { llinfos << "cof version change " << mVersion << " => " << version << llendl; } -#endif mVersion = version; } -- cgit v1.2.3 From b322c1dbaceaa9359243e030a125e312c54448f3 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 30 Apr 2013 16:54:52 -0400 Subject: SH-4140 FIX - removed a gratuitous log message --- indra/newview/llviewerinventory.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d45512df9c..f9afdee4f9 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -627,10 +627,6 @@ S32 LLViewerInventoryCategory::getVersion() const void LLViewerInventoryCategory::setVersion(S32 version) { - if (mPreferredType == LLFolderType::FT_CURRENT_OUTFIT) - { - llinfos << "cof version change " << mVersion << " => " << version << llendl; - } mVersion = version; } -- 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 +++++++++++++++++++++- indra/newview/llinventorymodel.h | 4 + indra/newview/llinventorymodelbackgroundfetch.cpp | 2 + 3 files changed, 202 insertions(+), 1 deletion(-) mode change 100644 => 100755 indra/newview/llinventorymodelbackgroundfetch.cpp (limited to 'indra/newview') 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 ///---------------------------------------------------------------------------- diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index b7e1888f20..2459f10a37 100755 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -227,6 +227,9 @@ public: // Check if one object has a parent chain up to the category specified by UUID. BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id) const; + // Follow parent chain to the top. + bool getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const; + //-------------------------------------------------------------------- // Find //-------------------------------------------------------------------- @@ -551,6 +554,7 @@ private: //-------------------------------------------------------------------- public: void dumpInventory() const; + bool validate() const; /** Miscellaneous ** ** diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp old mode 100644 new mode 100755 index 01b0e647a9..4eeb528c66 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -172,6 +172,8 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched() mRecursiveLibraryFetchStarted) { mAllFoldersFetched = TRUE; + //llinfos << "All folders fetched, validating" << llendl; + //gInventory.validate(); } mFolderFetchActive = false; } -- cgit v1.2.3 From af1431731802320e241037486b8bff0003a4d827 Mon Sep 17 00:00:00 2001 From: Nyx Linden Date: Thu, 2 May 2013 13:56:10 -0400 Subject: SH-4060 FIX avatar hover being set to minimum at seemingly random times avatar hover was being temporarily set to -2.0 for the preview render, which was triggering the minimum enforcement, even when the user's requested value is no where near the minimum. Added a flag to disable the minimum enforcement if we are temporarily changing the value. --- indra/newview/lltoolmorph.cpp | 12 ++++++++++++ indra/newview/llviewerwearable.h | 4 ++++ indra/newview/llvoavatar.cpp | 30 ++++++++++++++++++++++++++++++ indra/newview/llvoavatar.h | 3 +++ 4 files changed, 49 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp index 148e5a015b..f39b98dd31 100644 --- a/indra/newview/lltoolmorph.cpp +++ b/indra/newview/lltoolmorph.cpp @@ -54,6 +54,7 @@ #include "llviewercamera.h" #include "llviewertexturelist.h" #include "llviewerobject.h" +#include "llviewerwearable.h" #include "llviewerwindow.h" #include "llvoavatarself.h" #include "pipeline.h" @@ -147,6 +148,11 @@ BOOL LLVisualParamHint::needsRender() void LLVisualParamHint::preRender(BOOL clear_depth) { + LLViewerWearable* wearable = (LLViewerWearable*)mWearablePtr; + if (wearable) + { + wearable->setVolitile(TRUE); + } mLastParamWeight = mVisualParam->getWeight(); mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mVisualParamWeight, FALSE); gAgentAvatarp->setVisualParamWeight(mVisualParam->getID(), mVisualParamWeight, FALSE); @@ -239,6 +245,12 @@ BOOL LLVisualParamHint::render() } gAgentAvatarp->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight); mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight, FALSE); + LLViewerWearable* wearable = (LLViewerWearable*)mWearablePtr; + if (wearable) + { + wearable->setVolitile(FALSE); + } + gAgentAvatarp->updateVisualParams(); gGL.color4f(1,1,1,1); mGLTexturep->setGLTextureCreated(true); diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h index 65566f23a5..047b2ce143 100644 --- a/indra/newview/llviewerwearable.h +++ b/indra/newview/llviewerwearable.h @@ -68,6 +68,8 @@ public: void setParamsToDefaults(); void setTexturesToDefaults(); + void setVolitile(BOOL volitle) { mVolitle = volitle; } // TRUE when doing preview renders, some updates will be suppressed. + BOOL getVolitile() { return mVolitle; } /*virtual*/ LLUUID getDefaultTextureImageID(LLAvatarAppearanceDefines::ETextureIndex index) const; @@ -96,6 +98,8 @@ protected: LLAssetID mAssetID; LLTransactionID mTransactionID; + BOOL mVolitle; // True when rendering preview images. Can suppress some updates. + LLUUID mItemID; // ID of the inventory item in the agent's inventory }; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index a56e09cde0..919627c47c 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5214,6 +5214,36 @@ void LLVOAvatar::updateVisualParams() updateHeadOffset(); } +/*virtual*/ +void LLVOAvatar::computeBodySize() +{ + LLAvatarAppearance::computeBodySize(); + + // Certain configurations of avatars can force the overall height (with offset) to go negative. + // Enforce a constraint to make sure we don't go below 0.1 meters. + // Camera positioning and other things start to break down when your avatar is "walking" while being fully underground + if (isSelf() && getWearableData()) + { + LLViewerWearable* shape = (LLViewerWearable*)getWearableData()->getWearable(LLWearableType::WT_SHAPE, 0); + if (shape && shape->getVolitile()) + { + F32 hover_value = shape->getVisualParamWeight(AVATAR_HOVER); + if (hover_value < 0.0f && (mBodySize.mV[VZ] + hover_value < 1.1f)) + { + hover_value = -(mBodySize.mV[VZ] - 1.1f); // avoid floating point rounding making the above check continue to fail. + llassert(mBodySize.mV[VZ] + hover_value >= 1.1f); + + hover_value = llmin(hover_value, 0.0f); // don't force the hover value to be greater than 0. + + mAvatarOffset.mV[VZ] = hover_value; + shape->setVisualParamWeight(AVATAR_HOVER,hover_value, FALSE); + + } + } + } +} + + //----------------------------------------------------------------------------- // isActive() //----------------------------------------------------------------------------- diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 98e8491cb1..19ad49d3a1 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -212,6 +212,9 @@ public: /*virtual*/ LLVector3 getPosAgentFromGlobal(const LLVector3d &position); virtual void updateVisualParams(); + /*virtual*/ void computeBodySize(); + + /** Inherited ** ** -- cgit v1.2.3 From 668a822ace1a7f1dffd090bbdd68712c31d0ac5c Mon Sep 17 00:00:00 2001 From: Nyx Linden Date: Fri, 3 May 2013 17:30:36 -0400 Subject: SH-4147 FIX Macro avatars with hover==0 look incorrect on relog Inverted logic meant that we would enforce minimums only while in preview renders, not for actual user adjustments. This seems to fix it. --- indra/newview/llvoavatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 3189507b53..e2ed6f54cc 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5225,7 +5225,7 @@ void LLVOAvatar::computeBodySize() if (isSelf() && getWearableData()) { LLViewerWearable* shape = (LLViewerWearable*)getWearableData()->getWearable(LLWearableType::WT_SHAPE, 0); - if (shape && shape->getVolitile()) + if (shape && !shape->getVolitile()) { F32 hover_value = shape->getVisualParamWeight(AVATAR_HOVER); if (hover_value < 0.0f && (mBodySize.mV[VZ] + hover_value < 1.1f)) -- cgit v1.2.3 From e6bc0c5d695796c56bdc2a53f5db594e93e58aff Mon Sep 17 00:00:00 2001 From: Nyx Linden Date: Mon, 6 May 2013 18:31:17 -0400 Subject: SH-4147 FIX macro avatars with low hover look wrong after relog Preventing hover limit from being applied during startup or shutdown when the rigged mesh may not be fully loaded. --- indra/newview/llvoavatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index e2ed6f54cc..8e7bed39c4 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5222,7 +5222,7 @@ void LLVOAvatar::computeBodySize() // Certain configurations of avatars can force the overall height (with offset) to go negative. // Enforce a constraint to make sure we don't go below 0.1 meters. // Camera positioning and other things start to break down when your avatar is "walking" while being fully underground - if (isSelf() && getWearableData()) + if (isSelf() && getWearableData() && isFullyLoaded() && !LLApp::isQuitting()) { LLViewerWearable* shape = (LLViewerWearable*)getWearableData()->getWearable(LLWearableType::WT_SHAPE, 0); if (shape && !shape->getVolitile()) -- 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 +++++++++++++++++++++-- indra/newview/llinventorymodelbackgroundfetch.cpp | 1 + 2 files changed, 87 insertions(+), 6 deletions(-) (limited to 'indra/newview') 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 " diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 4eeb528c66..864f38cbde 100755 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -176,6 +176,7 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched() //gInventory.validate(); } mFolderFetchActive = false; + mBackgroundFetchActive = false; } void LLInventoryModelBackgroundFetch::backgroundFetchCB(void *) -- cgit v1.2.3 From 23c6016481ebc6de5433b9e9b9d07ebc4d5ae3cd Mon Sep 17 00:00:00 2001 From: Nyx Linden Date: Wed, 8 May 2013 16:34:12 -0400 Subject: SH-4048 SH-4171 SH-4046 FIX avatar sinks into ground, updates sent to observers Avatar preview code was triggering avatar size updates, which were causing the avatar's height above the ground to change when the previews were rendered. Also added code to suppress appearance updates being sent out while in appearance editing mode. --- indra/newview/llagent.cpp | 2 +- indra/newview/lltoolmorph.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 939d9398b2..883200c0f5 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -4296,7 +4296,7 @@ void LLAgent::sendAgentSetAppearance() return; } - if (!isAgentAvatarValid() || (getRegion() && getRegion()->getCentralBakeVersion())) return; + if (!isAgentAvatarValid() || gAgentAvatarp->isEditingAppearance() || (getRegion() && getRegion()->getCentralBakeVersion())) return; // At this point we have a complete appearance to send and are in a non-baking region. // DRANO FIXME diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp index f39b98dd31..fa94b52362 100644 --- a/indra/newview/lltoolmorph.cpp +++ b/indra/newview/lltoolmorph.cpp @@ -159,7 +159,9 @@ void LLVisualParamHint::preRender(BOOL clear_depth) gAgentAvatarp->setVisualParamWeight("Blink_Left", 0.f); gAgentAvatarp->setVisualParamWeight("Blink_Right", 0.f); gAgentAvatarp->updateComposites(); - gAgentAvatarp->updateVisualParams(); + // Calling LLCharacter version, as we don't want position/height changes to cause the avatar to jump + // up and down when we're doing preview renders. -Nyx + gAgentAvatarp->LLCharacter::updateVisualParams(); gAgentAvatarp->updateGeometry(gAgentAvatarp->mDrawable); gAgentAvatarp->updateLOD(); -- 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') 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 d4e537b3ef1319af451eeebc31bbe080242ed7d5 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 9 May 2013 16:41:55 -0400 Subject: SH-4176 WIP - made debugCOF() slightly harder to get to. --- indra/newview/llappearancemgr.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 40ec88f1be..543eb04c0b 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2947,7 +2947,7 @@ protected: void debugCOF(const LLSD& content) { - LL_DEBUGS("Avatar") << "AIS COF, version found: " << content["expected"].asInteger() << llendl; + LL_INFOS("Avatar") << "AIS COF, version found: " << content["expected"].asInteger() << llendl; std::set ais_items, local_items; const LLSD& cof_raw = content["cof_raw"]; for (LLSD::array_const_iterator it = cof_raw.beginArray(); @@ -2959,14 +2959,14 @@ protected: ais_items.insert(item["item_id"].asUUID()); if (item["type"].asInteger() == 24) // link { - LL_DEBUGS("Avatar") << "Link: item_id: " << item["item_id"].asUUID() + LL_INFOS("Avatar") << "Link: item_id: " << item["item_id"].asUUID() << " linked_item_id: " << item["asset_id"].asUUID() << " name: " << item["name"].asString() << llendl; } else if (item["type"].asInteger() == 25) // folder link { - LL_DEBUGS("Avatar") << "Folder link: item_id: " << item["item_id"].asUUID() + LL_INFOS("Avatar") << "Folder link: item_id: " << item["item_id"].asUUID() << " linked_item_id: " << item["asset_id"].asUUID() << " name: " << item["name"].asString() << llendl; @@ -2974,15 +2974,15 @@ protected: } else { - LL_DEBUGS("Avatar") << "Other: item_id: " << item["item_id"].asUUID() + LL_INFOS("Avatar") << "Other: item_id: " << item["item_id"].asUUID() << " linked_item_id: " << item["asset_id"].asUUID() << " name: " << item["name"].asString() << llendl; } } } - LL_DEBUGS("Avatar") << llendl; - LL_DEBUGS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() << llendl; + LL_INFOS("Avatar") << llendl; + LL_INFOS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() << llendl; LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), @@ -2991,24 +2991,24 @@ protected: { const LLViewerInventoryItem* inv_item = item_array.get(i).get(); local_items.insert(inv_item->getUUID()); - LL_DEBUGS("Avatar") << "item_id: " << inv_item->getUUID() + LL_INFOS("Avatar") << "item_id: " << inv_item->getUUID() << " linked_item_id: " << inv_item->getLinkedUUID() << " name: " << inv_item->getName() << llendl; } - LL_DEBUGS("Avatar") << llendl; + LL_INFOS("Avatar") << llendl; for (std::set::iterator it = local_items.begin(); it != local_items.end(); ++it) { if (ais_items.find(*it) == ais_items.end()) { - LL_DEBUGS("Avatar") << "LOCAL ONLY: " << *it << llendl; + LL_INFOS("Avatar") << "LOCAL ONLY: " << *it << llendl; } } for (std::set::iterator it = ais_items.begin(); it != ais_items.end(); ++it) { if (local_items.find(*it) == local_items.end()) { - LL_DEBUGS("Avatar") << "AIS ONLY: " << *it << llendl; + LL_INFOS("Avatar") << "AIS ONLY: " << *it << llendl; } } } -- cgit v1.2.3 From 55e686b0e305fa14ae5e40f7917f0ce3f3e3c6a1 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 10 May 2013 07:52:22 -0400 Subject: SH-4176 WIP - tweaks to debugCOF(), which shows differences between viewer and server side views of the COF when a mismatch occurs --- indra/newview/llappearancemgr.cpp | 49 ++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 19 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 543eb04c0b..e8bdb0d7ec 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2947,7 +2947,8 @@ protected: void debugCOF(const LLSD& content) { - LL_INFOS("Avatar") << "AIS COF, version found: " << content["expected"].asInteger() << llendl; + LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger() + << " ================================= " << llendl; std::set ais_items, local_items; const LLSD& cof_raw = content["cof_raw"]; for (LLSD::array_const_iterator it = cof_raw.beginArray(); @@ -2959,30 +2960,32 @@ protected: ais_items.insert(item["item_id"].asUUID()); if (item["type"].asInteger() == 24) // link { - LL_INFOS("Avatar") << "Link: item_id: " << item["item_id"].asUUID() - << " linked_item_id: " << item["asset_id"].asUUID() - << " name: " << item["name"].asString() - << llendl; + LL_INFOS("Avatar") << "AIS Link: item_id: " << item["item_id"].asUUID() + << " linked_item_id: " << item["asset_id"].asUUID() + << " name: " << item["name"].asString() + << llendl; } else if (item["type"].asInteger() == 25) // folder link { - LL_INFOS("Avatar") << "Folder link: item_id: " << item["item_id"].asUUID() - << " linked_item_id: " << item["asset_id"].asUUID() - << " name: " << item["name"].asString() - << llendl; + LL_INFOS("Avatar") << "AIS Folder link: item_id: " << item["item_id"].asUUID() + << " linked_item_id: " << item["asset_id"].asUUID() + << " name: " << item["name"].asString() + << llendl; } else { - LL_INFOS("Avatar") << "Other: item_id: " << item["item_id"].asUUID() - << " linked_item_id: " << item["asset_id"].asUUID() - << " name: " << item["name"].asString() - << llendl; + LL_INFOS("Avatar") << "AIS Other: item_id: " << item["item_id"].asUUID() + << " linked_item_id: " << item["asset_id"].asUUID() + << " name: " << item["name"].asString() + << " type: " << item["type"].asInteger() + << llendl; } } } LL_INFOS("Avatar") << llendl; - LL_INFOS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() << llendl; + LL_INFOS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() + << " ================================= " << llendl; LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), @@ -2991,12 +2994,13 @@ protected: { const LLViewerInventoryItem* inv_item = item_array.get(i).get(); local_items.insert(inv_item->getUUID()); - LL_INFOS("Avatar") << "item_id: " << inv_item->getUUID() - << " linked_item_id: " << inv_item->getLinkedUUID() - << " name: " << inv_item->getName() - << llendl; + LL_INFOS("Avatar") << "LOCAL: item_id: " << inv_item->getUUID() + << " linked_item_id: " << inv_item->getLinkedUUID() + << " name: " << inv_item->getName() + << " parent: " << inv_item->getParentUUID() + << llendl; } - LL_INFOS("Avatar") << llendl; + LL_INFOS("Avatar") << " ================================= " << llendl; for (std::set::iterator it = local_items.begin(); it != local_items.end(); ++it) { if (ais_items.find(*it) == ais_items.end()) @@ -3011,6 +3015,13 @@ protected: LL_INFOS("Avatar") << "AIS ONLY: " << *it << llendl; } } + if (local_items.size()==0 && ais_items.size()==0) + { + LL_INFOS("Avatar") << "COF contents identical, only version numbers differ (req " + << content["observed"].asInteger() + << " rcv " << content["expected"].asInteger() + << ")" << llendl; + } } LLPointer mRetryPolicy; -- cgit v1.2.3 From 43224062a64cc658d429e434a7b673fac0b7c012 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 10 May 2013 09:19:34 -0400 Subject: SH-4176 WIP - avoid raw dump of whole error contents in log file --- indra/newview/llappearancemgr.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index e8bdb0d7ec..3c141aa37a 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2905,15 +2905,14 @@ protected: // Error /*virtual*/ void httpFailure() { - const LLSD& content = getContent(); - LL_WARNS("Avatar") << "appearance update request failed " - << dumpResponse() << LL_ENDL; + LL_WARNS("Avatar") << "appearance update request failed, status " + << getStatus() << " reason " << getReason() << LL_ENDL; if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) { + const LLSD& content = getContent(); dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_error", content); debugCOF(content); - } onFailure(); } -- cgit v1.2.3 From 96a2173c643e145a6f5d4964282c4d43f0fc0c3e Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 10 May 2013 09:32:30 -0400 Subject: SH-4176 WIP - allow retries on 4xx errors if enabled by flag. So enable in the case of appearance requests. --- indra/newview/llappearancemgr.cpp | 3 ++- indra/newview/llhttpretrypolicy.cpp | 7 ++++--- indra/newview/llhttpretrypolicy.h | 3 ++- indra/newview/tests/llhttpretrypolicy_test.cpp | 15 +++++++++++---- 4 files changed, 19 insertions(+), 9 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 3c141aa37a..84a494186f 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2871,7 +2871,8 @@ class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder public: RequestAgentUpdateAppearanceResponder() { - mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10); + bool retry_on_4xx = true; + mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10, retry_on_4xx); } virtual ~RequestAgentUpdateAppearanceResponder() diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp index 80d97e4362..1512b46103 100755 --- a/indra/newview/llhttpretrypolicy.cpp +++ b/indra/newview/llhttpretrypolicy.cpp @@ -28,11 +28,12 @@ #include "llhttpretrypolicy.h" -LLAdaptiveRetryPolicy::LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries): +LLAdaptiveRetryPolicy::LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries, bool retry_on_4xx): mMinDelay(min_delay), mMaxDelay(max_delay), mBackoffFactor(backoff_factor), - mMaxRetries(max_retries) + mMaxRetries(max_retries), + mRetryOn4xx(retry_on_4xx) { init(); } @@ -108,7 +109,7 @@ void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_ti llinfos << "Too many retries " << mRetryCount << ", will not retry" << llendl; mShouldRetry = false; } - if (!isHttpServerErrorStatus(status)) + if (!mRetryOn4xx && !isHttpServerErrorStatus(status)) { llinfos << "Non-server error " << status << ", will not retry" << llendl; mShouldRetry = false; diff --git a/indra/newview/llhttpretrypolicy.h b/indra/newview/llhttpretrypolicy.h index 1fb0cac03f..5b1a1d79e0 100755 --- a/indra/newview/llhttpretrypolicy.h +++ b/indra/newview/llhttpretrypolicy.h @@ -60,7 +60,7 @@ public: class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy { public: - LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries); + LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries, bool retry_on_4xx = false); // virtual void onSuccess(); @@ -88,6 +88,7 @@ private: U32 mRetryCount; // number of times shouldRetry has been called. LLTimer mRetryTimer; // time until next retry. bool mShouldRetry; // Becomes false after too many retries, or the wrong sort of status received, etc. + bool mRetryOn4xx; // Normally only retry on 5xx server errors. }; #endif diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp index ed7f3ba326..25e6de46d9 100755 --- a/indra/newview/tests/llhttpretrypolicy_test.cpp +++ b/indra/newview/tests/llhttpretrypolicy_test.cpp @@ -56,12 +56,19 @@ void RetryPolicyTestObject::test<1>() template<> template<> void RetryPolicyTestObject::test<2>() { - LLAdaptiveRetryPolicy retry404(1.0,2.0,3.0,10); LLSD headers; F32 wait_seconds; - - retry404.onFailure(404,headers); - ensure("no retry on 404", !retry404.shouldRetry(wait_seconds)); + + // Normally only retry on server error (5xx) + LLAdaptiveRetryPolicy noRetry404(1.0,2.0,3.0,10); + noRetry404.onFailure(404,headers); + ensure("no retry on 404", !noRetry404.shouldRetry(wait_seconds)); + + // Can retry on 4xx errors if enabled by flag. + bool do_retry_4xx = true; + LLAdaptiveRetryPolicy doRetry404(1.0,2.0,3.0,10,do_retry_4xx); + doRetry404.onFailure(404,headers); + ensure("do retry on 404", doRetry404.shouldRetry(wait_seconds)); } template<> template<> -- cgit v1.2.3 From 5c219f694a97d010332618eff9de7bdbeb5b6ed6 Mon Sep 17 00:00:00 2001 From: Nyx Linden Date: Fri, 10 May 2013 12:58:41 -0400 Subject: DEBUG adding additional logging for avatar height usually disabled, enable avatar in logcontrol.xml to get output. --- indra/newview/llagent.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 883200c0f5..d7ab68ccd1 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -4337,7 +4337,9 @@ void LLAgent::sendAgentSetAppearance() // to compensate for the COLLISION_TOLERANCE ugliness we will have // to tweak this number again const LLVector3 body_size = gAgentAvatarp->mBodySize + gAgentAvatarp->mAvatarOffset; - msg->addVector3Fast(_PREHASH_Size, body_size); + msg->addVector3Fast(_PREHASH_Size, body_size); + + LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Sent AgentSetAppearance with height: " << body_size.mv[VZ] << " base: " << gAgentAvatarp->mBodySize.mV[VZ] << " hover: " << gAgentAvatarp->mAvatarOffset.mV[VZ] << LL_ENDL; // To guard against out of order packets // Note: always start by sending 1. This resets the server's count. 0 on the server means "uninitialized" -- cgit v1.2.3 From cd9acddf09ba80a3a2249194256217882c71bf7c Mon Sep 17 00:00:00 2001 From: Nyx Linden Date: Fri, 10 May 2013 13:04:18 -0400 Subject: BUILDFIX capitalization error --- indra/newview/llagent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index d7ab68ccd1..21625815b9 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -4339,7 +4339,7 @@ void LLAgent::sendAgentSetAppearance() const LLVector3 body_size = gAgentAvatarp->mBodySize + gAgentAvatarp->mAvatarOffset; msg->addVector3Fast(_PREHASH_Size, body_size); - LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Sent AgentSetAppearance with height: " << body_size.mv[VZ] << " base: " << gAgentAvatarp->mBodySize.mV[VZ] << " hover: " << gAgentAvatarp->mAvatarOffset.mV[VZ] << LL_ENDL; + LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Sent AgentSetAppearance with height: " << body_size.mV[VZ] << " base: " << gAgentAvatarp->mBodySize.mV[VZ] << " hover: " << gAgentAvatarp->mAvatarOffset.mV[VZ] << LL_ENDL; // To guard against out of order packets // Note: always start by sending 1. This resets the server's count. 0 on the server means "uninitialized" -- cgit v1.2.3 From 3f1d360a04c4e4d8f07b7e93cd926961ae379430 Mon Sep 17 00:00:00 2001 From: "prep@lindenlab.com" Date: Fri, 10 May 2013 13:57:02 -0500 Subject: SH-4035: Removed prompt to save if av just has outfit changes. Hooked up logic to handle ctrl+w and ctrl+shift+w confirmation prompts --- indra/newview/llfloatersidepanelcontainer.cpp | 33 +++++++++++++++++++++++++++ indra/newview/llfloatersidepanelcontainer.h | 3 ++- indra/newview/llsidepanelappearance.cpp | 22 ++++++++++-------- 3 files changed, 47 insertions(+), 11 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index 4dd558c9c0..43ee54ecd2 100644 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -45,6 +45,39 @@ LLFloaterSidePanelContainer::LLFloaterSidePanelContainer(const LLSD& key, const // Prevent transient floaters (e.g. IM windows) from hiding // when this floater is clicked. LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::GLOBAL, this); + //We want this container to handle the shutdown logic of the sidepanelappearance. + mVerifyUponClose = TRUE; +} + +BOOL LLFloaterSidePanelContainer::postBuild() +{ + setCloseConfirmationCallback( boost::bind(&LLFloaterSidePanelContainer::onConfirmationClose,this,_2)); + return TRUE; +} + +void LLFloaterSidePanelContainer::onConfirmationClose( const LLSD &confirm ) +{ + /* + LLPanelOutfitEdit* panel_outfit_edit = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit")); + if (panel_outfit_edit) + { + LLFloater *parent = gFloaterView->getParentFloater(panel_outfit_edit); + if (parent == this ) + { + LLSidepanelAppearance* panel_appearance = dynamic_cast(getPanel("appearance")); + panel_appearance->onClose(this); + } + else + { + LLFloater::onClickCloseBtn(); + } + } + else + { + LLFloater::onClickCloseBtn(); + } + */ + onClickCloseBtn(); } LLFloaterSidePanelContainer::~LLFloaterSidePanelContainer() diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h index 940673b643..26fc092200 100644 --- a/indra/newview/llfloatersidepanelcontainer.h +++ b/indra/newview/llfloatersidepanelcontainer.h @@ -50,8 +50,9 @@ public: ~LLFloaterSidePanelContainer(); /*virtual*/ void onOpen(const LLSD& key); - /*virtual*/ void onClickCloseBtn(); + /*virtual*/ BOOL postBuild(); + void onConfirmationClose( const LLSD &confirm ); LLPanel* openChildPanel(const std::string& panel_name, const LLSD& params); diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 77e9604460..f77275fd1c 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -90,11 +90,12 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if ( option == 0 ) { - //revert curernt edits - mEditWearable->revertChanges(); - toggleWearableEditPanel(FALSE); - LLVOAvatarSelf::onCustomizeEnd(FALSE); - mLLFloaterSidePanelContainer->close(); + //revert current edits + mEditWearable->revertChanges(); + //LLAppearanceMgr::getInstance()->wearBaseOutfit(); + toggleWearableEditPanel(FALSE); + LLVOAvatarSelf::onCustomizeEnd( FALSE ); + mLLFloaterSidePanelContainer->close(); return true; } return false; @@ -115,7 +116,7 @@ void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaClose() void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack() { - if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !mSidePanelJustOpened && !LLAppearanceMgr::getInstance()->isOutfitLocked() ) + if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !mSidePanelJustOpened /*&& !LLAppearanceMgr::getInstance()->isOutfitLocked()*/ ) { LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this; LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaBack,pSelf,_1,_2) ); @@ -128,9 +129,9 @@ void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack() void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj) { - mLLFloaterSidePanelContainer = obj; - if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && - !LLAppearanceMgr::getInstance()->isOutfitLocked() || + mLLFloaterSidePanelContainer = obj; + if ( /*LLAppearanceMgr::getInstance()->isOutfitDirty() && */ + /*!LLAppearanceMgr::getInstance()->isOutfitLocked() ||*/ ( mEditWearable->isAvailable() && mEditWearable->isDirty() ) ) { LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this; @@ -275,8 +276,9 @@ void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility) void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility) { - if (new_visibility["visible"].asBoolean()) + if (new_visibility["visible"].asBoolean() ) { + const BOOL is_outfit_edit_visible = mOutfitEdit && mOutfitEdit->getVisible(); const BOOL is_wearable_edit_visible = mEditWearable && mEditWearable->getVisible(); -- cgit v1.2.3 From 69df2f1b0430dc00519b08bd2f0abd6712d3d2bc Mon Sep 17 00:00:00 2001 From: "prep@lindenlab.com" Date: Mon, 13 May 2013 11:54:37 -0500 Subject: SH-4035: Hooked up logic to handle 'me->appearance'. Refactored out some commonly used code in llfloatersidepanelcontainer --- indra/newview/llfloatersidepanelcontainer.cpp | 83 +++++++++++++++------------ indra/newview/llfloatersidepanelcontainer.h | 5 ++ indra/newview/llsidepanelappearance.cpp | 34 +++++++++++ indra/newview/llsidepanelappearance.h | 4 +- 4 files changed, 87 insertions(+), 39 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index 43ee54ecd2..3ea39cf196 100644 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -56,30 +56,11 @@ BOOL LLFloaterSidePanelContainer::postBuild() } void LLFloaterSidePanelContainer::onConfirmationClose( const LLSD &confirm ) -{ - /* - LLPanelOutfitEdit* panel_outfit_edit = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit")); - if (panel_outfit_edit) - { - LLFloater *parent = gFloaterView->getParentFloater(panel_outfit_edit); - if (parent == this ) - { - LLSidepanelAppearance* panel_appearance = dynamic_cast(getPanel("appearance")); - panel_appearance->onClose(this); - } - else - { - LLFloater::onClickCloseBtn(); - } - } - else - { - LLFloater::onClickCloseBtn(); - } - */ +{ onClickCloseBtn(); } + LLFloaterSidePanelContainer::~LLFloaterSidePanelContainer() { LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::GLOBAL, this); @@ -92,20 +73,10 @@ void LLFloaterSidePanelContainer::onOpen(const LLSD& key) void LLFloaterSidePanelContainer::onClickCloseBtn() { - LLPanelOutfitEdit* panel_outfit_edit = - dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit")); - if (panel_outfit_edit) + LLSidepanelAppearance* panel = getSidePanelAppearance(); + if ( panel ) { - LLFloater *parent = gFloaterView->getParentFloater(panel_outfit_edit); - if (parent == this ) - { - LLSidepanelAppearance* panel_appearance = dynamic_cast(getPanel("appearance")); - panel_appearance->onClose(this); - } - else - { - LLFloater::onClickCloseBtn(); - } + panel->onClose( this ); } else { @@ -114,7 +85,7 @@ void LLFloaterSidePanelContainer::onClickCloseBtn() } void LLFloaterSidePanelContainer::close() { - LLFloater::onClickCloseBtn(); + LLFloater::onClickCloseBtn(); } LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_name, const LLSD& params) @@ -124,7 +95,7 @@ LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_na if (!getVisible()) { - openFloater(); + openFloater(); } LLPanel* panel = NULL; @@ -145,10 +116,30 @@ LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_na void LLFloaterSidePanelContainer::showPanel(const std::string& floater_name, const LLSD& key) { - LLFloaterSidePanelContainer* floaterp = LLFloaterReg::getTypedInstance(floater_name); + //If we're already open then check whether anything is dirty + LLFloaterSidePanelContainer* floaterp = LLFloaterReg::getTypedInstance(floater_name); if (floaterp) { - floaterp->openChildPanel(sMainPanelName, key); + if ( floaterp->getVisible() ) + { + LLSidepanelAppearance* panel = floaterp->getSidePanelAppearance(); + if ( panel ) + { + if ( panel->checkForDirtyEdits() ) + { + panel->onClickConfirmExitWithoutSaveIntoAppearance(); + } + else + { + //or a call into some new f() that just shows inv panel? + floaterp->openChildPanel(sMainPanelName, key); + } + } + } + else + { + floaterp->openChildPanel(sMainPanelName, key); + } } } @@ -172,3 +163,19 @@ LLPanel* LLFloaterSidePanelContainer::getPanel(const std::string& floater_name, return NULL; } + +LLSidepanelAppearance* LLFloaterSidePanelContainer::getSidePanelAppearance() +{ + LLSidepanelAppearance* panel_appearance = NULL; + LLPanelOutfitEdit* panel_outfit_edit = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit")); + if (panel_outfit_edit) + { + LLFloater *parent = gFloaterView->getParentFloater(panel_outfit_edit); + if (parent == this ) + { + panel_appearance = dynamic_cast(getPanel("appearance")); + } + } + return panel_appearance; + +} \ No newline at end of file diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h index 26fc092200..974934b48f 100644 --- a/indra/newview/llfloatersidepanelcontainer.h +++ b/indra/newview/llfloatersidepanelcontainer.h @@ -30,6 +30,8 @@ #include "llfloater.h" +class LLSidepanelAppearance; + /** * Class LLFloaterSidePanelContainer * @@ -81,6 +83,9 @@ public: } return panel; } + +private: + LLSidepanelAppearance* getSidePanelAppearance(); }; #endif // LL_LLFLOATERSIDEPANELCONTAINER_H diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index f77275fd1c..cf759dd8f7 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -114,6 +114,35 @@ void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaClose() } } + +bool LLSidepanelAppearance::callBackExitWithoutSaveIntoAppearance(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if ( option == 0 ) + { + //revert current edits + mEditWearable->revertChanges(); + toggleWearableEditPanel(FALSE); + LLVOAvatarSelf::onCustomizeEnd( FALSE ); + //mLLFloaterSidePanelContainer->close(); + showOutfitsInventoryPanel(); + return true; + } + return false; +} + +void LLSidepanelAppearance::onClickConfirmExitWithoutSaveIntoAppearance() +{ + if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !LLAppearanceMgr::getInstance()->isOutfitLocked() ) + { + LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this; + LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveIntoAppearance,pSelf,_1,_2) ); + } + else + { + showOutfitsInventoryPanel(); + } +} void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack() { if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !mSidePanelJustOpened /*&& !LLAppearanceMgr::getInstance()->isOutfitLocked()*/ ) @@ -629,3 +658,8 @@ void LLSidepanelAppearance::updateScrollingPanelList() mEditWearable->updateScrollingPanelList(); } } + +bool LLSidepanelAppearance::checkForDirtyEdits() +{ + return ( mEditWearable->isDirty() ) ? true : false; +} \ No newline at end of file diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h index 85e7734567..caf5be62e9 100644 --- a/indra/newview/llsidepanelappearance.h +++ b/indra/newview/llsidepanelappearance.h @@ -73,7 +73,9 @@ public: void onClickConfirmExitWithoutSaveViaBack(); bool callBackExitWithoutSaveViaClose(const LLSD& notification, const LLSD& response); void onClickConfirmExitWithoutSaveViaClose(); - + bool checkForDirtyEdits(); + bool callBackExitWithoutSaveIntoAppearance(const LLSD& notification, const LLSD& response); + void onClickConfirmExitWithoutSaveIntoAppearance(); private: void onFilterEdit(const std::string& search_string); -- cgit v1.2.3 From b7161fcd58853fb60900e51a4ac221b02941905e Mon Sep 17 00:00:00 2001 From: "prep@lindenlab.com" Date: Mon, 13 May 2013 16:03:22 -0500 Subject: SH-4035: Removed prompt to save if av just has outfit changes and you click on the back button --- indra/newview/llsidepanelappearance.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index cf759dd8f7..1b56aff3b6 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -145,12 +145,14 @@ void LLSidepanelAppearance::onClickConfirmExitWithoutSaveIntoAppearance() } void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack() { - if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !mSidePanelJustOpened /*&& !LLAppearanceMgr::getInstance()->isOutfitLocked()*/ ) + /* + if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !mSidePanelJustOpened && !LLAppearanceMgr::getInstance()->isOutfitLocked() ) { LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this; LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaBack,pSelf,_1,_2) ); } else + */ { showOutfitsInventoryPanel(); } -- 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/llinventorybridge.cpp | 18 ++++---- indra/newview/llinventorymodel.cpp | 85 +++++++++++++++++++++++++++++++++---- indra/newview/llinventorymodel.h | 11 +++-- indra/newview/llviewerinventory.cpp | 8 ++-- 4 files changed, 96 insertions(+), 26 deletions(-) mode change 100644 => 100755 indra/newview/llinventorybridge.cpp (limited to 'indra/newview') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp old mode 100644 new mode 100755 index 27f35c5946..abebd0aa5e --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1566,18 +1566,18 @@ void LLItemBridge::buildDisplayName() const else { mDisplayName.assign(LLStringUtil::null); -} - + } + mSearchableName.assign(mDisplayName); mSearchableName.append(getLabelSuffix()); LLStringUtil::toUpper(mSearchableName); - + //Name set, so trigger a sort if(mParent) -{ - mParent->requestSort(); - } + { + mParent->requestSort(); } +} LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const { @@ -1901,8 +1901,7 @@ void LLFolderBridge::update() possibly_has_children = true; } - bool loading = (possibly_has_children - && !up_to_date ); + bool loading = (possibly_has_children && !up_to_date ); if (loading != mIsLoading) { @@ -1929,12 +1928,13 @@ void LLFolderBridge::update() || (LLInventoryModelBackgroundFetch::instance().folderFetchActive() && root_is_loading)) { + buildDisplayName(); mDisplayName = LLInvFVBridge::getDisplayName() + " ( " + LLTrans::getString("LoadingData") + " ) "; mIsLoading = true; } else { - mDisplayName = LLInvFVBridge::getDisplayName(); + buildDisplayName(); mIsLoading = false; } } 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); } diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 2459f10a37..696d0a9163 100755 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -328,19 +328,22 @@ public: // Delete //-------------------------------------------------------------------- public: - + + // Update model after an AISv3 update received for any operation. + void onAISUpdateReceived(const std::string& context, const LLSD& update); + // Update model after an item is confirmed as removed from // server. Works for categories or items. - void onObjectDeletedFromServer(const LLUUID& item_id); + void onObjectDeletedFromServer(const LLUUID& item_id, bool fix_broken_links = true); // Update model after all descendents removed from server. - void onDescendentsPurgedFromServer(const LLUUID& object_id); + void onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links = true); // Delete a particular inventory object by ID. Will purge one // object from the internal data structures, maintaining a // consistent internal state. No cache accounting, observer // notification, or server update is performed. - void deleteObject(const LLUUID& id); + void deleteObject(const LLUUID& id, bool fix_broken_links = true); /// move Item item_id to Trash void removeItem(const LLUUID& item_id); /// move Category category_id to Trash diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index f9afdee4f9..5ffd560942 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1154,8 +1154,8 @@ public: failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); return; } - llinfos << "succeeded: " << ll_pretty_print_sd(content) << llendl; - + gInventory.onAISUpdateReceived("removeObjectResponder " + mItemUUID.asString(), content); + // FIXME - not needed after AIS starts returning deleted item in its response. gInventory.onObjectDeletedFromServer(mItemUUID); if (mCallback) @@ -1335,9 +1335,7 @@ public: failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); return; } - llinfos << "succeeded: " << ll_pretty_print_sd(content) << llendl; - - gInventory.onDescendentsPurgedFromServer(mItemUUID); + gInventory.onAISUpdateReceived("purgeDescendentsResponder " + mItemUUID.asString(), content); if (mCallback) { -- cgit v1.2.3 From 931410211e1d644028f5b09cbf77b179e0e75aab Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 15 May 2013 09:45:10 -0400 Subject: SH-4144 FIX - removed UseAISv3Inventory debug settings - cap is now managed sim-side --- indra/newview/app_settings/settings.xml | 11 ----------- indra/newview/llviewerinventory.cpp | 6 +++--- 2 files changed, 3 insertions(+), 14 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 1262089b3d..18a33b3542 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -14033,17 +14033,6 @@ Value 1 - UseAISv3Inventory - - Comment - Allow use of AISv3 inventory - this setting should only be needed during development. - Persist - 1 - Type - Boolean - Value - 0 - ClickToWalk Comment diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 5ffd560942..e819479923 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1189,7 +1189,7 @@ void remove_inventory_item( if(obj) { std::string cap; - if (gAgent.getRegion() && gSavedSettings.getBOOL("UseAISv3Inventory")) + if (gAgent.getRegion()) { cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); } @@ -1267,7 +1267,7 @@ void remove_inventory_category( } std::string cap; - if (gAgent.getRegion() && gSavedSettings.getBOOL("UseAISv3Inventory")) + if (gAgent.getRegion()) { cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); } @@ -1407,7 +1407,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer cb) else { std::string cap; - if (gAgent.getRegion() && gSavedSettings.getBOOL("UseAISv3Inventory")) + if (gAgent.getRegion()) { cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); } -- cgit v1.2.3 From 2ed3746aee81901435f3f28f71a497d234d680d2 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 15 May 2013 13:27:16 -0400 Subject: SH-4197 FIX - also simplified the category remove flow for AIS, don't need to purge descendents first. --- indra/newview/llviewerinventory.cpp | 39 ++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index e819479923..202ed43caa 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1155,8 +1155,6 @@ public: return; } gInventory.onAISUpdateReceived("removeObjectResponder " + mItemUUID.asString(), content); - // FIXME - not needed after AIS starts returning deleted item in its response. - gInventory.onObjectDeletedFromServer(mItemUUID); if (mCallback) { @@ -1226,18 +1224,26 @@ void remove_inventory_item( } } -class LLRemoveObjectOnDestroy: public LLInventoryCallback +class LLRemoveCategoryOnDestroy: public LLInventoryCallback { public: - LLRemoveObjectOnDestroy(const LLUUID& item_id, LLPointer cb): - mID(item_id), + LLRemoveCategoryOnDestroy(const LLUUID& cat_id, LLPointer cb): + mID(cat_id), mCB(cb) { } /* virtual */ void fire(const LLUUID& item_id) {} - ~LLRemoveObjectOnDestroy() + ~LLRemoveCategoryOnDestroy() { - remove_inventory_object(mID, mCB); + LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(mID); + if(children != LLInventoryModel::CHILDREN_NO) + { + llwarns << "remove descendents failed, cannot remove category " << llendl; + } + else + { + remove_inventory_category(mID, mCB); + } } private: LLUUID mID; @@ -1257,15 +1263,6 @@ void remove_inventory_category( LLNotificationsUtil::add("CannotRemoveProtectedCategories"); return; } - LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(cat_id); - if(children != LLInventoryModel::CHILDREN_NO) - { - llinfos << "Will purge descendents first before deleting category " << cat_id << llendl; - LLPointer wrap_cb = new LLRemoveObjectOnDestroy(cat_id,cb); - purge_descendents_of(cat_id, wrap_cb); - return; - } - std::string cap; if (gAgent.getRegion()) { @@ -1280,6 +1277,16 @@ void remove_inventory_category( } else // no cap { + // RemoveInventoryFolder does not remove children, so must + // clear descendents first. + LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(cat_id); + if(children != LLInventoryModel::CHILDREN_NO) + { + llinfos << "Will purge descendents first before deleting category " << cat_id << llendl; + LLPointer wrap_cb = new LLRemoveCategoryOnDestroy(cat_id, cb); + purge_descendents_of(cat_id, wrap_cb); + return; + } LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_RemoveInventoryFolder); -- cgit v1.2.3 From 8a4add76b44bab32633c5432f8852e5351770c91 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 15 May 2013 18:08:12 -0400 Subject: SH-4175 WIP - Avoid add to outfit or remove from outfit when an outfit change is already in progress --- indra/newview/llappearancemgr.cpp | 14 +++++++++++--- indra/newview/llinventorybridge.cpp | 4 ++++ indra/newview/llviewerinventory.cpp | 2 +- 3 files changed, 16 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 84a494186f..f48755ecce 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1547,6 +1547,11 @@ bool LLAppearanceMgr::getCanRemoveOutfit(const LLUUID& outfit_cat_id) // static bool LLAppearanceMgr::getCanRemoveFromCOF(const LLUUID& outfit_cat_id) { + if (gAgentWearables.isCOFChangeInProgress()) + { + return false; + } + LLFindWearablesEx is_worn(/*is_worn=*/ true, /*include_body_parts=*/ false); return gInventory.hasMatchingDirectDescendent(outfit_cat_id, is_worn); } @@ -1578,8 +1583,8 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id) } // Check whether the outfit contains any wearables we aren't wearing already (STORM-702). - LLFindWearablesEx is_worn(/*is_worn=*/ false, /*include_body_parts=*/ true); - return gInventory.hasMatchingDirectDescendent(outfit_cat_id, is_worn); + LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ true); + return gInventory.hasMatchingDirectDescendent(outfit_cat_id, not_worn); } void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer cb) @@ -3001,11 +3006,13 @@ protected: << llendl; } LL_INFOS("Avatar") << " ================================= " << llendl; + S32 local_only = 0, ais_only = 0; for (std::set::iterator it = local_items.begin(); it != local_items.end(); ++it) { if (ais_items.find(*it) == ais_items.end()) { LL_INFOS("Avatar") << "LOCAL ONLY: " << *it << llendl; + local_only++; } } for (std::set::iterator it = ais_items.begin(); it != ais_items.end(); ++it) @@ -3013,9 +3020,10 @@ protected: if (local_items.find(*it) == local_items.end()) { LL_INFOS("Avatar") << "AIS ONLY: " << *it << llendl; + ais_only++; } } - if (local_items.size()==0 && ais_items.size()==0) + if (local_only==0 && ais_only==0) { LL_INFOS("Avatar") << "COF contents identical, only version numbers differ (req " << content["observed"].asInteger() diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index abebd0aa5e..b857f8bbec 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3579,6 +3579,10 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& { disabled_items.push_back(std::string("Replace Outfit")); } + if (!LLAppearanceMgr::instance().getCanAddToCOF(mUUID)) + { + disabled_items.push_back(std::string("Add To Outfit")); + } items.push_back(std::string("Outfit Separator")); } } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 202ed43caa..18ea812471 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1182,8 +1182,8 @@ void remove_inventory_item( const LLUUID& item_id, LLPointer cb) { - llinfos << "item_id: [" << item_id << "] " << llendl; LLPointer obj = gInventory.getItem(item_id); + llinfos << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl; if(obj) { std::string cap; -- cgit v1.2.3 From 14a3c5187b644b084f0b0a024a8ac953e89f37de Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 16 May 2013 14:40:04 -0400 Subject: SH-4175 WIP - removed a case where we request to delete the base outfit link twice when changing outfits --- indra/newview/llappearancemgr.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index f48755ecce..cfe9055aab 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1765,7 +1765,10 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) // the link_waiter so links can be followed for any items that get // carried over (e.g. keeping old shape if the new outfit does not // contain one) - bool keep_outfit_links = append; + + // even in the non-append case, createBaseOutfitLink() already + // deletes the existing link, don't need to do it again here. + bool keep_outfit_links = true; removeCategoryContents(cof, keep_outfit_links, link_waiter); LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL; -- cgit v1.2.3 From 14f7ad902330051e1bb3ff17abbbfa05a0ebf7e8 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Thu, 16 May 2013 19:17:52 -0700 Subject: SH-4168 FIX Inventory: Loading... Loading... shown on folders cleaned up logic for displaying "loading..." message so that it only applies to folders that are opened whose contents aren't yet loaded --- indra/newview/llinventorybridge.cpp | 48 ++++++++++--------------------------- indra/newview/llinventorybridge.h | 4 +++- 2 files changed, 16 insertions(+), 36 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index b857f8bbec..c32abe507e 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -200,6 +200,7 @@ const std::string& LLInvFVBridge::getDisplayName() const { buildDisplayName(); } + return mDisplayName; } @@ -1894,49 +1895,19 @@ void LLFolderBridge::buildDisplayName() const void LLFolderBridge::update() { - bool possibly_has_children = false; - bool up_to_date = isUpToDate(); - if(!up_to_date && hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter) - { - possibly_has_children = true; - } - - bool loading = (possibly_has_children && !up_to_date ); + // we know we have children but haven't fetched them (doesn't obey filter) + bool loading = !isUpToDate() && hasChildren() && mFolderViewItem->isOpen(); if (loading != mIsLoading) { - if ( loading && !mIsLoading ) + if ( loading ) { // Measure how long we've been in the loading state mTimeSinceRequestStart.reset(); } + mIsLoading = loading; - const BOOL in_inventory = gInventory.isObjectDescendentOf(getUUID(), gInventory.getRootFolderID()); - const BOOL in_library = gInventory.isObjectDescendentOf(getUUID(), gInventory.getLibraryRootFolderID()); - - bool root_is_loading = false; - if (in_inventory) - { - root_is_loading = LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress(); - } - if (in_library) - { - root_is_loading = LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress(); - } - if ((mIsLoading - && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) - || (LLInventoryModelBackgroundFetch::instance().folderFetchActive() - && root_is_loading)) - { - buildDisplayName(); - mDisplayName = LLInvFVBridge::getDisplayName() + " ( " + LLTrans::getString("LoadingData") + " ) "; - mIsLoading = true; - } - else - { - buildDisplayName(); - mIsLoading = false; - } + mFolderViewItem->refresh(); } } @@ -3056,6 +3027,13 @@ LLUIImagePtr LLFolderBridge::getIconOverlay() const return NULL; } +std::string LLFolderBridge::getLabelSuffix() const +{ + static LLCachedControl folder_loading_message_delay(gSavedSettings, "FolderLoadingMessageWaitTime"); + return mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= folder_loading_message_delay() + ? llformat(" ( %s ) ", LLTrans::getString("LoadingData").c_str()) + : LLStringUtil::null; +} BOOL LLFolderBridge::renameItem(const std::string& new_name) { diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 517153e171..2a937b574d 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -248,7 +248,7 @@ public: LLFolderBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid) - : LLInvFVBridge(inventory, root, uuid), + : LLInvFVBridge(inventory, root, uuid), mCallingCards(FALSE), mWearables(FALSE), mIsLoading(false) @@ -272,6 +272,8 @@ public: virtual LLUIImagePtr getIconOverlay() const; static LLUIImagePtr getIcon(LLFolderType::EType preferred_type); + + virtual std::string getLabelSuffix() const; virtual BOOL renameItem(const std::string& new_name); -- cgit v1.2.3 From d09db5949050ac23547e1cd06712ebbf9a980b2a Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 17 May 2013 18:01:52 -0400 Subject: SH-4200 WIP - added AISCommand classes with retry capabilities. --- indra/newview/llviewerinventory.cpp | 205 +++++++++++++++++++++++------------- 1 file changed, 131 insertions(+), 74 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 18ea812471..31ff3bb5d6 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -66,6 +66,7 @@ #include "lllogininstance.h" #include "llfavoritesbar.h" #include "llclipboard.h" +#include "llhttpretrypolicy.h" // Two do-nothing ops for use in callbacks. void no_op_inventory_func(const LLUUID&) {} @@ -1138,44 +1139,156 @@ void move_inventory_item( gAgent.sendReliableMessage(); } -class RemoveObjectResponder: public LLHTTPClient::Responder +class AISCommand: public LLHTTPClient::Responder { public: - RemoveObjectResponder(const LLUUID& item_id, LLPointer callback): - mItemUUID(item_id), + typedef boost::function command_func_type; + + AISCommand(LLPointer callback): mCallback(callback) { + llinfos << "constructor" << llendl; + mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10); + } + + virtual ~AISCommand() + { + llinfos << "destructor" << llendl; + } + + void run_command() + { + mCommandFunc(); + } + + void setCommandFunc(command_func_type command_func) + { + mCommandFunc = command_func; + } + + // Need to do command-specific parsing to get an id here. May or + // may not need to bother, since most LLInventoryCallbacks do + // their work in the destructor. + virtual bool getResponseUUID(const LLSD& content, LLUUID& id) + { + return false; } + /* virtual */ void httpSuccess() { + // Command func holds a reference to self, need to release it + // after a success or final failure. + setCommandFunc(no_op); + const LLSD& content = getContent(); if (!content.isMap()) { failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); return; } - gInventory.onAISUpdateReceived("removeObjectResponder " + mItemUUID.asString(), content); + mRetryPolicy->onSuccess(); + + gInventory.onAISUpdateReceived("AISCommand", content); if (mCallback) { - mCallback->fire(mItemUUID); + LLUUID item_id; // will default to null if parse fails. + getResponseUUID(content,item_id); + mCallback->fire(item_id); } } + /*virtual*/ void httpFailure() { const LLSD& content = getContent(); S32 status = getStatus(); const std::string& reason = getReason(); + const LLSD& headers = getResponseHeaders(); if (!content.isMap()) { - llwarns << "Malformed response contents " << content << " id " << mItemUUID << " status " << status << " reason " << reason << llendl; - return; + llwarns << "Malformed response contents " << content + << " status " << status << " reason " << reason << llendl; + } + else + { + llwarns << "failed with content: " << ll_pretty_print_sd(content) + << " status " << status << " reason " << reason << llendl; + } + mRetryPolicy->onFailure(status, headers); + F32 seconds_to_wait; + if (mRetryPolicy->shouldRetry(seconds_to_wait)) + { + doAfterInterval(boost::bind(&AISCommand::run_command,this),seconds_to_wait); + } + else + { + // Command func holds a reference to self, need to release it + // after a success or final failure. + setCommandFunc(no_op); } - llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << " status " << status << " reason " << reason << llendl; } + + static bool getCap(std::string& cap) + { + if (gAgent.getRegion()) + { + cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); + } + if (!cap.empty()) + { + return true; + } + return false; + } + private: + command_func_type mCommandFunc; + LLPointer mRetryPolicy; LLPointer mCallback; - const LLUUID mItemUUID; +}; + +class RemoveObjectCommand: public AISCommand +{ +public: + RemoveObjectCommand(const LLUUID& item_id, + LLPointer callback): + AISCommand(callback) + { + std::string cap; + if (!getCap(cap)) + { + return; + } + const std::string url = cap + std::string("/item/") + item_id.asString(); + llinfos << "url: " << url << llendl; + LLHTTPClient::ResponderPtr responder = this; + LLSD headers; + F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout); + setCommandFunc(cmd); + } +}; + +class PurgeDescendentsCommand: public AISCommand +{ +public: + PurgeDescendentsCommand(const LLUUID& item_id, + LLPointer callback): + AISCommand(callback) + { + std::string cap; + if (!getCap(cap)) + { + return; + } + std::string url = cap + std::string("/category/") + item_id.asString() + "/children"; + llinfos << "url: " << url << llendl; + LLCurl::ResponderPtr responder = this; + LLSD headers; + F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout); + setCommandFunc(cmd); + } }; void remove_inventory_item( @@ -1187,16 +1300,10 @@ void remove_inventory_item( if(obj) { std::string cap; - if (gAgent.getRegion()) - { - cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); - } - if (!cap.empty()) + if (AISCommand::getCap(cap)) { - std::string url = cap + std::string("/item/") + item_id.asString(); - llinfos << "url: " << url << llendl; - LLCurl::ResponderPtr responder_ptr = new RemoveObjectResponder(item_id,cb); - LLHTTPClient::del(url,responder_ptr); + LLPointer cmd_ptr = new RemoveObjectCommand(item_id, cb); + cmd_ptr->run_command(); } else // no cap { @@ -1264,16 +1371,12 @@ void remove_inventory_category( return; } std::string cap; - if (gAgent.getRegion()) - { - cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); - } - if (!cap.empty()) + if (AISCommand::getCap(cap)) { std::string url = cap + std::string("/category/") + cat_id.asString(); llinfos << "url: " << url << llendl; - LLCurl::ResponderPtr responder_ptr = new RemoveObjectResponder(cat_id,cb); - LLHTTPClient::del(url,responder_ptr); + LLPointer cmd_ptr = new RemoveObjectCommand(cat_id, cb); + cmd_ptr->run_command(); } else // no cap { @@ -1326,46 +1429,6 @@ void remove_inventory_object( } } -class PurgeDescendentsResponder: public LLHTTPClient::Responder -{ -public: - PurgeDescendentsResponder(const LLUUID& item_id, LLPointer callback): - mItemUUID(item_id), - mCallback(callback) - { - } - /* virtual */ void httpSuccess() - { - const LLSD& content = getContent(); - if (!content.isMap()) - { - failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); - return; - } - gInventory.onAISUpdateReceived("purgeDescendentsResponder " + mItemUUID.asString(), content); - - if (mCallback) - { - mCallback->fire(mItemUUID); - } - } - /*virtual*/ void httpFailure() - { - const LLSD& content = getContent(); - S32 status = getStatus(); - const std::string& reason = getReason(); - if (!content.isMap()) - { - llwarns << "Malformed response contents " << content << " id " << mItemUUID << " status " << status << " reason " << reason << llendl; - return; - } - llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << " status " << status << " reason " << reason << llendl; - } -private: - LLPointer mCallback; - const LLUUID mItemUUID; -}; - // 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 @@ -1414,16 +1477,10 @@ void purge_descendents_of(const LLUUID& id, LLPointer cb) else { std::string cap; - if (gAgent.getRegion()) - { - cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); - } - if (!cap.empty()) + if (AISCommand::getCap(cap)) { - std::string url = cap + std::string("/category/") + id.asString() + "/children"; - llinfos << "url: " << url << llendl; - LLCurl::ResponderPtr responder_ptr = new PurgeDescendentsResponder(id,cb); - LLHTTPClient::del(url,responder_ptr); + LLPointer cmd_ptr = new PurgeDescendentsCommand(id, cb); + cmd_ptr->run_command(); } else // no cap { -- 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/app_settings/logcontrol.xml | 1 + indra/newview/llinventorymodel.cpp | 28 +++++++------ indra/newview/llviewerinventory.cpp | 67 ++++++++++++++++++++----------- 3 files changed, 60 insertions(+), 36 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 92a241857e..6594fdb249 100755 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -43,6 +43,7 @@ tags 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); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 31ff3bb5d6..50d67463c7 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1147,13 +1147,11 @@ public: AISCommand(LLPointer callback): mCallback(callback) { - llinfos << "constructor" << llendl; mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10); } virtual ~AISCommand() { - llinfos << "destructor" << llendl; } void run_command() @@ -1206,13 +1204,13 @@ public: const LLSD& headers = getResponseHeaders(); if (!content.isMap()) { - llwarns << "Malformed response contents " << content - << " status " << status << " reason " << reason << llendl; + LL_DEBUGS("Inventory") << "Malformed response contents " << content + << " status " << status << " reason " << reason << llendl; } else { - llwarns << "failed with content: " << ll_pretty_print_sd(content) - << " status " << status << " reason " << reason << llendl; + LL_DEBUGS("Inventory") << "failed with content: " << ll_pretty_print_sd(content) + << " status " << status << " reason " << reason << llendl; } mRetryPolicy->onFailure(status, headers); F32 seconds_to_wait; @@ -1247,20 +1245,44 @@ private: LLPointer mCallback; }; -class RemoveObjectCommand: public AISCommand +class RemoveItemCommand: public AISCommand { public: - RemoveObjectCommand(const LLUUID& item_id, - LLPointer callback): + RemoveItemCommand(const LLUUID& item_id, + LLPointer callback): AISCommand(callback) { std::string cap; if (!getCap(cap)) { + llwarns << "No cap found" << llendl; return; } - const std::string url = cap + std::string("/item/") + item_id.asString(); - llinfos << "url: " << url << llendl; + std::string url = cap + std::string("/item/") + item_id.asString(); + LL_DEBUGS("Inventory") << "url: " << url << llendl; + LLHTTPClient::ResponderPtr responder = this; + LLSD headers; + F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout); + setCommandFunc(cmd); + } +}; + +class RemoveCategoryCommand: public AISCommand +{ +public: + RemoveCategoryCommand(const LLUUID& item_id, + LLPointer callback): + AISCommand(callback) + { + std::string cap; + if (!getCap(cap)) + { + llwarns << "No cap found" << llendl; + return; + } + std::string url = cap + std::string("/category/") + item_id.asString(); + LL_DEBUGS("Inventory") << "url: " << url << llendl; LLHTTPClient::ResponderPtr responder = this; LLSD headers; F32 timeout = HTTP_REQUEST_EXPIRY_SECS; @@ -1279,10 +1301,11 @@ public: std::string cap; if (!getCap(cap)) { + llwarns << "No cap found" << llendl; return; } std::string url = cap + std::string("/category/") + item_id.asString() + "/children"; - llinfos << "url: " << url << llendl; + LL_DEBUGS("Inventory") << "url: " << url << llendl; LLCurl::ResponderPtr responder = this; LLSD headers; F32 timeout = HTTP_REQUEST_EXPIRY_SECS; @@ -1296,13 +1319,13 @@ void remove_inventory_item( LLPointer cb) { LLPointer obj = gInventory.getItem(item_id); - llinfos << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl; + LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl; if(obj) { std::string cap; if (AISCommand::getCap(cap)) { - LLPointer cmd_ptr = new RemoveObjectCommand(item_id, cb); + LLPointer cmd_ptr = new RemoveItemCommand(item_id, cb); cmd_ptr->run_command(); } else // no cap @@ -1361,7 +1384,7 @@ void remove_inventory_category( const LLUUID& cat_id, LLPointer cb) { - llinfos << "cat_id: [" << cat_id << "] " << llendl; + LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] " << llendl; LLPointer obj = gInventory.getCategory(cat_id); if(obj) { @@ -1373,9 +1396,7 @@ void remove_inventory_category( std::string cap; if (AISCommand::getCap(cap)) { - std::string url = cap + std::string("/category/") + cat_id.asString(); - llinfos << "url: " << url << llendl; - LLPointer cmd_ptr = new RemoveObjectCommand(cat_id, cb); + LLPointer cmd_ptr = new RemoveCategoryCommand(cat_id, cb); cmd_ptr->run_command(); } else // no cap @@ -1385,7 +1406,7 @@ void remove_inventory_category( LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(cat_id); if(children != LLInventoryModel::CHILDREN_NO) { - llinfos << "Will purge descendents first before deleting category " << cat_id << llendl; + LL_DEBUGS("Inventory") << "Will purge descendents first before deleting category " << cat_id << llendl; LLPointer wrap_cb = new LLRemoveCategoryOnDestroy(cat_id, cb); purge_descendents_of(cat_id, wrap_cb); return; @@ -1439,7 +1460,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer cb) LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(id); if(children == LLInventoryModel::CHILDREN_NO) { - llinfos << "No descendents to purge for " << id << llendl; + LL_DEBUGS("Inventory") << "No descendents to purge for " << id << llendl; return; } LLPointer cat = gInventory.getCategory(id); @@ -1448,8 +1469,8 @@ void purge_descendents_of(const LLUUID& id, LLPointer cb) if (LLClipboard::instance().hasContents() && LLClipboard::instance().isCutMode()) { // Something on the clipboard is in "cut mode" and needs to be preserved - llinfos << "purge_descendents_of clipboard case " << cat->getName() - << " iterate and purge non hidden items" << llendl; + LL_DEBUGS("Inventory") << "purge_descendents_of clipboard case " << cat->getName() + << " iterate and purge non hidden items" << llendl; LLInventoryModel::cat_array_t* categories; LLInventoryModel::item_array_t* items; // Get the list of direct descendants in tha categoy passed as argument @@ -1485,7 +1506,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer cb) else // no cap { // Fast purge - llinfos << "purge_descendents_of fast case " << cat->getName() << llendl; + LL_DEBUGS("Inventory") << "purge_descendents_of fast case " << cat->getName() << llendl; // send it upstream LLMessageSystem* msg = gMessageSystem; -- 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/llappearancemgr.cpp | 4 +- indra/newview/llinventorybridge.cpp | 10 +- indra/newview/llinventoryfunctions.cpp | 9 +- indra/newview/llinventorymodel.cpp | 93 +++++- indra/newview/llinventorymodel.h | 6 + indra/newview/llviewerinventory.cpp | 510 +++++++++++++++++++++++---------- indra/newview/llviewerinventory.h | 14 + 7 files changed, 475 insertions(+), 171 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index cfe9055aab..14eed6e1df 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2812,8 +2812,10 @@ struct WearablesOrderComparator //items with ordering information but not for the associated wearables type if (!item1_valid && item2_valid) return false; + else if (item1_valid && !item2_valid) + return true; - return true; + return item1->getName() < item2->getName(); } U32 mControlSize; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index c32abe507e..89c56ab82c 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1692,13 +1692,9 @@ BOOL LLItemBridge::renameItem(const std::string& new_name) LLViewerInventoryItem* item = getItem(); if(item && (item->getName() != new_name)) { - LLPointer new_item = new LLViewerInventoryItem(item); - new_item->rename(new_name); - new_item->updateServer(FALSE); - model->updateItem(new_item); - - model->notifyObservers(); - buildDisplayName(); + LLSD updates; + updates["name"] = new_name; + update_inventory_item(item->getUUID(),updates, NULL); } // return FALSE because we either notified observers (& therefore // rebuilt) or we didn't update. diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index f1a4889f5a..b5fb226872 100755 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -123,12 +123,9 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s return; } - LLPointer new_cat = new LLViewerInventoryCategory(cat); - new_cat->rename(new_name); - new_cat->updateServer(FALSE); - model->updateCategory(new_cat); - - model->notifyObservers(); + LLSD updates; + updates["name"] = new_name; + update_inventory_category(cat_id, updates, NULL); } void copy_inventory_category(LLInventoryModel* model, 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) { diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 696d0a9163..515c99c0b4 100755 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -339,6 +339,12 @@ public: // Update model after all descendents removed from server. void onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links = true); + // Update model after an existing item gets updated on server. + void onItemUpdated(const LLUUID& item_id, const LLSD& updates); + + // Update model after an existing category gets updated on server. + void onCategoryUpdated(const LLUUID& cat_id, const LLSD& updates); + // Delete a particular inventory object by ID. Will purge one // object from the internal data structures, maintaining a // consistent internal state. No cache accounting, observer diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 50d67463c7..90fef3b5ed 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -259,6 +259,240 @@ public: LLInventoryHandler gInventoryHandler; +///---------------------------------------------------------------------------- +/// Classes for AISv3 support. +///---------------------------------------------------------------------------- +class AISCommand: public LLHTTPClient::Responder +{ +public: + typedef boost::function command_func_type; + + AISCommand(LLPointer callback): + mCallback(callback) + { + mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10); + } + + virtual ~AISCommand() + { + } + + void run_command() + { + mCommandFunc(); + } + + void setCommandFunc(command_func_type command_func) + { + mCommandFunc = command_func; + } + + // Need to do command-specific parsing to get an id here. May or + // may not need to bother, since most LLInventoryCallbacks do + // their work in the destructor. + virtual bool getResponseUUID(const LLSD& content, LLUUID& id) + { + return false; + } + + /* virtual */ void httpSuccess() + { + // Command func holds a reference to self, need to release it + // after a success or final failure. + setCommandFunc(no_op); + + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + mRetryPolicy->onSuccess(); + + gInventory.onAISUpdateReceived("AISCommand", content); + + if (mCallback) + { + LLUUID item_id; // will default to null if parse fails. + getResponseUUID(content,item_id); + mCallback->fire(item_id); + } + } + + /*virtual*/ void httpFailure() + { + const LLSD& content = getContent(); + S32 status = getStatus(); + const std::string& reason = getReason(); + const LLSD& headers = getResponseHeaders(); + if (!content.isMap()) + { + LL_DEBUGS("Inventory") << "Malformed response contents " << content + << " status " << status << " reason " << reason << llendl; + } + else + { + LL_DEBUGS("Inventory") << "failed with content: " << ll_pretty_print_sd(content) + << " status " << status << " reason " << reason << llendl; + } + mRetryPolicy->onFailure(status, headers); + F32 seconds_to_wait; + if (mRetryPolicy->shouldRetry(seconds_to_wait)) + { + doAfterInterval(boost::bind(&AISCommand::run_command,this),seconds_to_wait); + } + else + { + // Command func holds a reference to self, need to release it + // after a success or final failure. + setCommandFunc(no_op); + } + } + + static bool getCap(std::string& cap) + { + if (gAgent.getRegion()) + { + cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); + } + if (!cap.empty()) + { + return true; + } + return false; + } + +private: + command_func_type mCommandFunc; + LLPointer mRetryPolicy; + LLPointer mCallback; +}; + +class RemoveItemCommand: public AISCommand +{ +public: + RemoveItemCommand(const LLUUID& item_id, + LLPointer callback): + AISCommand(callback) + { + std::string cap; + if (!getCap(cap)) + { + llwarns << "No cap found" << llendl; + return; + } + std::string url = cap + std::string("/item/") + item_id.asString(); + LL_DEBUGS("Inventory") << "url: " << url << llendl; + LLHTTPClient::ResponderPtr responder = this; + LLSD headers; + F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout); + setCommandFunc(cmd); + } +}; + +class RemoveCategoryCommand: public AISCommand +{ +public: + RemoveCategoryCommand(const LLUUID& item_id, + LLPointer callback): + AISCommand(callback) + { + std::string cap; + if (!getCap(cap)) + { + llwarns << "No cap found" << llendl; + return; + } + std::string url = cap + std::string("/category/") + item_id.asString(); + LL_DEBUGS("Inventory") << "url: " << url << llendl; + LLHTTPClient::ResponderPtr responder = this; + LLSD headers; + F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout); + setCommandFunc(cmd); + } +}; + +class PurgeDescendentsCommand: public AISCommand +{ +public: + PurgeDescendentsCommand(const LLUUID& item_id, + LLPointer callback): + AISCommand(callback) + { + std::string cap; + if (!getCap(cap)) + { + llwarns << "No cap found" << llendl; + return; + } + std::string url = cap + std::string("/category/") + item_id.asString() + "/children"; + LL_DEBUGS("Inventory") << "url: " << url << llendl; + LLCurl::ResponderPtr responder = this; + LLSD headers; + F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout); + setCommandFunc(cmd); + } +}; + +class UpdateItemCommand: public AISCommand +{ +public: + UpdateItemCommand(const LLUUID& item_id, + const LLSD& updates, + LLPointer callback): + mUpdates(updates), + AISCommand(callback) + { + std::string cap; + if (!getCap(cap)) + { + llwarns << "No cap found" << llendl; + return; + } + std::string url = cap + std::string("/item/") + item_id.asString(); + LL_DEBUGS("Inventory") << "url: " << url << llendl; + LLCurl::ResponderPtr responder = this; + LLSD headers; + headers["Content-Type"] = "application/llsd+xml"; + F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder, headers, timeout); + setCommandFunc(cmd); + } +private: + LLSD mUpdates; +}; + +class UpdateCategoryCommand: public AISCommand +{ +public: + UpdateCategoryCommand(const LLUUID& item_id, + const LLSD& updates, + LLPointer callback): + mUpdates(updates), + AISCommand(callback) + { + std::string cap; + if (!getCap(cap)) + { + llwarns << "No cap found" << llendl; + return; + } + std::string url = cap + std::string("/category/") + item_id.asString(); + LL_DEBUGS("Inventory") << "url: " << url << llendl; + LLCurl::ResponderPtr responder = this; + LLSD headers; + headers["Content-Type"] = "application/llsd+xml"; + F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder, headers, timeout); + setCommandFunc(cmd); + } +private: + LLSD mUpdates; +}; + ///---------------------------------------------------------------------------- /// Class LLViewerInventoryItem ///---------------------------------------------------------------------------- @@ -456,6 +690,20 @@ void LLViewerInventoryItem::setTransactionID(const LLTransactionID& transaction_ // virtual void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const { + static const LLSD updates; + packUpdateMessage(msg,updates); +} + +void LLViewerInventoryItem::packUpdateMessage(LLMessageSystem* msg, const LLSD& updates) const +{ + for (LLSD::map_const_iterator it = updates.beginMap(); it != updates.endMap(); ++it) + { + if ((it->first != "desc") && (it->first != "name")) + { + llerrs << "unhandled field: " << it->first << llendl; + } + } + msg->addUUIDFast(_PREHASH_ItemID, mUUID); msg->addUUIDFast(_PREHASH_FolderID, mParentUUID); mPermissions.packMessage(msg); @@ -466,12 +714,29 @@ void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const msg->addS8Fast(_PREHASH_InvType, type); msg->addU32Fast(_PREHASH_Flags, mFlags); mSaleInfo.packMessage(msg); - msg->addStringFast(_PREHASH_Name, mName); - msg->addStringFast(_PREHASH_Description, mDescription); + if (updates.has("name")) + { + std::string new_name = updates["name"].asString(); + LLInventoryObject::correctInventoryName(new_name); + msg->addStringFast(_PREHASH_Name, new_name); + } + else + { + msg->addStringFast(_PREHASH_Name, mName); + } + if (updates.has("desc")) + { + msg->addStringFast(_PREHASH_Description, updates["desc"].asString()); + } + else + { + msg->addStringFast(_PREHASH_Description, mDescription); + } msg->addS32Fast(_PREHASH_CreationDate, mCreationDate); U32 crc = getCRC32(); msg->addU32Fast(_PREHASH_CRC, crc); } + // virtual BOOL LLViewerInventoryItem::importFile(LLFILE* fp) { @@ -583,6 +848,32 @@ void LLViewerInventoryCategory::copyViewerCategory(const LLViewerInventoryCatego } +void LLViewerInventoryCategory::packUpdateMessage(LLMessageSystem* msg, const LLSD& updates) const +{ + for (LLSD::map_const_iterator it = updates.beginMap(); it != updates.endMap(); ++it) + { + if (it->first != "name") + { + llerrs << "unhandled field: " << it->first << llendl; + } + } + + msg->addUUIDFast(_PREHASH_FolderID, mUUID); + msg->addUUIDFast(_PREHASH_ParentID, mParentUUID); + S8 type = static_cast(mPreferredType); + msg->addS8Fast(_PREHASH_Type, type); + if (updates.has("name")) + { + std::string new_name = updates["name"].asString(); + LLInventoryObject::correctInventoryName(new_name); + msg->addStringFast(_PREHASH_Name, new_name); + } + else + { + msg->addStringFast(_PREHASH_Name, mName); + } +} + void LLViewerInventoryCategory::updateParentOnServer(BOOL restamp) const { LLMessageSystem* msg = gMessageSystem; @@ -1139,180 +1430,87 @@ void move_inventory_item( gAgent.sendReliableMessage(); } -class AISCommand: public LLHTTPClient::Responder +// Note this only supports updating an existing item. Goes through AISv3 +// code path where available. Not all uses of item->updateServer() can +// easily be switched to this paradigm. +void update_inventory_item( + const LLUUID& item_id, + const LLSD& updates, + LLPointer cb) { -public: - typedef boost::function command_func_type; - - AISCommand(LLPointer callback): - mCallback(callback) - { - mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10); - } - - virtual ~AISCommand() - { - } - - void run_command() - { - mCommandFunc(); - } - - void setCommandFunc(command_func_type command_func) - { - mCommandFunc = command_func; - } - - // Need to do command-specific parsing to get an id here. May or - // may not need to bother, since most LLInventoryCallbacks do - // their work in the destructor. - virtual bool getResponseUUID(const LLSD& content, LLUUID& id) - { - return false; - } - - /* virtual */ void httpSuccess() - { - // Command func holds a reference to self, need to release it - // after a success or final failure. - setCommandFunc(no_op); - - const LLSD& content = getContent(); - if (!content.isMap()) - { - failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); - return; - } - mRetryPolicy->onSuccess(); - - gInventory.onAISUpdateReceived("AISCommand", content); - - if (mCallback) - { - LLUUID item_id; // will default to null if parse fails. - getResponseUUID(content,item_id); - mCallback->fire(item_id); - } - } - - /*virtual*/ void httpFailure() + LLPointer obj = gInventory.getItem(item_id); + LL_DEBUGS("Inventory") << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl; + if(obj) { - const LLSD& content = getContent(); - S32 status = getStatus(); - const std::string& reason = getReason(); - const LLSD& headers = getResponseHeaders(); - if (!content.isMap()) - { - LL_DEBUGS("Inventory") << "Malformed response contents " << content - << " status " << status << " reason " << reason << llendl; - } - else - { - LL_DEBUGS("Inventory") << "failed with content: " << ll_pretty_print_sd(content) - << " status " << status << " reason " << reason << llendl; - } - mRetryPolicy->onFailure(status, headers); - F32 seconds_to_wait; - if (mRetryPolicy->shouldRetry(seconds_to_wait)) + std::string cap; + if (AISCommand::getCap(cap)) { - doAfterInterval(boost::bind(&AISCommand::run_command,this),seconds_to_wait); + LLPointer cmd_ptr = new UpdateItemCommand(item_id, updates, cb); + cmd_ptr->run_command(); } - else + else // no cap { - // Command func holds a reference to self, need to release it - // after a success or final failure. - setCommandFunc(no_op); - } - } + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_UpdateInventoryItem); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_TransactionID, obj->getTransactionID()); + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addU32Fast(_PREHASH_CallbackID, 0); + obj->packUpdateMessage(msg, updates); + gAgent.sendReliableMessage(); - static bool getCap(std::string& cap) - { - if (gAgent.getRegion()) - { - cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); - } - if (!cap.empty()) - { - return true; + gInventory.onItemUpdated(item_id, updates); + if (cb) + { + cb->fire(item_id); + } } - return false; } +} -private: - command_func_type mCommandFunc; - LLPointer mRetryPolicy; - LLPointer mCallback; -}; - -class RemoveItemCommand: public AISCommand +void update_inventory_category( + const LLUUID& cat_id, + const LLSD& updates, + LLPointer cb) { -public: - RemoveItemCommand(const LLUUID& item_id, - LLPointer callback): - AISCommand(callback) + LLPointer obj = gInventory.getCategory(cat_id); + LL_DEBUGS("Inventory") << "cat_id: [" << cat_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << llendl; + if(obj) { - std::string cap; - if (!getCap(cap)) + if (LLFolderType::lookupIsProtectedType(obj->getPreferredType())) { - llwarns << "No cap found" << llendl; + LLNotificationsUtil::add("CannotModifyProtectedCategories"); return; } - std::string url = cap + std::string("/item/") + item_id.asString(); - LL_DEBUGS("Inventory") << "url: " << url << llendl; - LLHTTPClient::ResponderPtr responder = this; - LLSD headers; - F32 timeout = HTTP_REQUEST_EXPIRY_SECS; - command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout); - setCommandFunc(cmd); - } -}; -class RemoveCategoryCommand: public AISCommand -{ -public: - RemoveCategoryCommand(const LLUUID& item_id, - LLPointer callback): - AISCommand(callback) - { - std::string cap; - if (!getCap(cap)) + //std::string cap; + // FIXME - restore this once the back-end work has been done. + if (0) // if (AISCommand::getCap(cap)) { - llwarns << "No cap found" << llendl; - return; + LLPointer cmd_ptr = new UpdateCategoryCommand(cat_id, updates, cb); + cmd_ptr->run_command(); } - std::string url = cap + std::string("/category/") + item_id.asString(); - LL_DEBUGS("Inventory") << "url: " << url << llendl; - LLHTTPClient::ResponderPtr responder = this; - LLSD headers; - F32 timeout = HTTP_REQUEST_EXPIRY_SECS; - command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout); - setCommandFunc(cmd); - } -}; - -class PurgeDescendentsCommand: public AISCommand -{ -public: - PurgeDescendentsCommand(const LLUUID& item_id, - LLPointer callback): - AISCommand(callback) - { - std::string cap; - if (!getCap(cap)) + else // no cap { - llwarns << "No cap found" << llendl; - return; + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_UpdateInventoryFolder); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_FolderData); + obj->packUpdateMessage(msg, updates); + gAgent.sendReliableMessage(); + + gInventory.onCategoryUpdated(cat_id, updates); + if (cb) + { + cb->fire(cat_id); + } } - std::string url = cap + std::string("/category/") + item_id.asString() + "/children"; - LL_DEBUGS("Inventory") << "url: " << url << llendl; - LLCurl::ResponderPtr responder = this; - LLSD headers; - F32 timeout = HTTP_REQUEST_EXPIRY_SECS; - command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout); - setCommandFunc(cmd); } -}; +} void remove_inventory_item( const LLUUID& item_id, diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 4e24dc87d1..c52b0c2d9d 100755 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -139,6 +139,8 @@ public: //void updateAssetOnServer() const; virtual void packMessage(LLMessageSystem* msg) const; + // Contents of updates will take precedence over fields of item where they differ. + void packUpdateMessage(LLMessageSystem* msg, const LLSD& updates) const; virtual void setTransactionID(const LLTransactionID& transaction_id); struct comparePointers { @@ -224,6 +226,8 @@ public: void determineFolderType(); void changeType(LLFolderType::EType new_folder_type); + void packUpdateMessage(LLMessageSystem* msg, const LLSD& updates) const; + private: friend class LLInventoryModel; void localizeName(); // intended to be called from the LLInventoryModel @@ -363,6 +367,16 @@ void move_inventory_item( const std::string& new_name, LLPointer cb); +void update_inventory_item( + const LLUUID& item_id, + const LLSD& updates, + LLPointer cb); + +void update_inventory_category( + const LLUUID& cat_id, + const LLSD& updates, + LLPointer cb); + void remove_inventory_item( const LLUUID& item_id, LLPointer cb); -- 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/llappearancemgr.cpp | 96 ++++++++++++++++++++----------------- indra/newview/llappearancemgr.h | 12 +++-- indra/newview/llinventorymodel.cpp | 51 ++++---------------- indra/newview/llinventorymodel.h | 2 +- indra/newview/llviewerinventory.cpp | 6 ++- 5 files changed, 74 insertions(+), 93 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 14eed6e1df..83ad06a3c7 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -422,10 +422,12 @@ public: }; LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering, - bool enforce_item_restrictions): + bool enforce_item_restrictions, + bool enforce_ordering): mFireCount(0), mUpdateBaseOrder(update_base_outfit_ordering), - mEnforceItemRestrictions(enforce_item_restrictions) + mEnforceItemRestrictions(enforce_item_restrictions), + mEnforceOrdering(enforce_ordering) { selfStartPhase("update_appearance_on_destroy"); } @@ -449,7 +451,7 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy() selfStopPhase("update_appearance_on_destroy"); - LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder, mEnforceItemRestrictions); + LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder, mEnforceItemRestrictions, mEnforceOrdering); } } @@ -1918,8 +1920,22 @@ void LLAppearanceMgr::findAllExcessOrDuplicateItems(const LLUUID& cat_id, -1, items_to_kill); } +void LLAppearanceMgr::enforceCOFItemRestrictions(LLPointer cb) +{ + LLInventoryModel::item_array_t items_to_kill; + findAllExcessOrDuplicateItems(getCOF(), items_to_kill); + if (items_to_kill.size()>0) + { + // Remove duplicate or excess wearables. Should normally be enforced at the UI level, but + // this should catch anything that gets through. + removeAll(items_to_kill, cb); + return; + } +} + void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering, - bool enforce_item_restrictions) + bool enforce_item_restrictions, + bool enforce_ordering) { if (mIsInUpdateAppearanceFromCOF) { @@ -1927,35 +1943,37 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering, return; } - BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF); - selfStartPhase("update_appearance_from_cof"); - LL_DEBUGS("Avatar") << self_av_string() << "starting" << LL_ENDL; if (enforce_item_restrictions) { - LLInventoryModel::item_array_t items_to_kill; - findAllExcessOrDuplicateItems(getCOF(), items_to_kill); - if (items_to_kill.size()>0) - { - // The point here is just to call - // updateAppearanceFromCOF() again after excess items - // have been removed. That time we will set - // enforce_item_restrictions to false so we don't get - // caught in a perpetual loop. - LLPointer cb( - new LLUpdateAppearanceOnDestroy(update_base_outfit_ordering, false)); - - // Remove duplicate or excess wearables. Should normally be enforced at the UI level, but - // this should catch anything that gets through. - removeAll(items_to_kill, cb); - return; - } + // The point here is just to call + // updateAppearanceFromCOF() again after excess items + // have been removed. That time we will set + // enforce_item_restrictions to false so we don't get + // caught in a perpetual loop. + LLPointer cb( + new LLUpdateAppearanceOnDestroy(update_base_outfit_ordering, false, enforce_ordering)); + enforceCOFItemRestrictions(cb); + return; } - //checking integrity of the COF in terms of ordering of wearables, - //checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state) - updateClothingOrderingInfo(LLUUID::null, update_base_outfit_ordering); + if (enforce_ordering) + { + //checking integrity of the COF in terms of ordering of wearables, + //checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state) + + // As with enforce_item_restrictions handling above, we want + // to wait for the update callbacks, then (finally!) call + // updateAppearanceFromCOF() with no additional COF munging needed. + LLPointer cb( + new LLUpdateAppearanceOnDestroy(false, false, false)); + updateClothingOrderingInfo(LLUUID::null, update_base_outfit_ordering, cb); + return; + } + + BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF); + selfStartPhase("update_appearance_from_cof"); // update dirty flag to see if the state of the COF matches // the saved outfit stored as a folder link @@ -1966,11 +1984,6 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering, { requestServerAppearanceUpdate(); } - // DRANO really should wait for the appearance message to set this. - // verify that deleting this line doesn't break anything. - //gAgentAvatarp->setIsUsingServerBakes(gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion()); - - //dumpCat(getCOF(),"COF, start"); LLUUID current_outfit_id = getCOF(); @@ -2821,7 +2834,9 @@ struct WearablesOrderComparator U32 mControlSize; }; -void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base_outfit_ordering) +void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, + bool update_base_outfit_ordering, + LLPointer cb) { if (cat_id.isNull()) { @@ -2831,7 +2846,7 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base const LLUUID base_outfit_id = getBaseOutfitUUID(); if (base_outfit_id.notNull()) { - updateClothingOrderingInfo(base_outfit_id,false); + updateClothingOrderingInfo(base_outfit_id,false,cb); } } } @@ -2843,7 +2858,6 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base wearables_by_type_t items_by_type(LLWearableType::WT_COUNT); divvyWearablesByType(wear_items, items_by_type); - bool inventory_changed = false; for (U32 type = LLWearableType::WT_SHIRT; type < LLWearableType::WT_COUNT; type++) { @@ -2862,17 +2876,11 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base std::string new_order_str = build_order_string((LLWearableType::EType)type, i); if (new_order_str == item->getActualDescription()) continue; - item->setDescription(new_order_str); - item->setComplete(TRUE); - item->updateServer(FALSE); - gInventory.updateItem(item); - - inventory_changed = true; + LLSD updates; + updates["desc"] = new_order_str; + update_inventory_item(item->getUUID(),updates,cb); } } - - //*TODO do we really need to notify observers? - if (inventory_changed) gInventory.notifyObservers(); } class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 2cc76c4b4c..246401ae85 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -50,7 +50,8 @@ public: typedef std::vector wearables_by_type_t; void updateAppearanceFromCOF(bool update_base_outfit_ordering = false, - bool enforce_item_restrictions = true); + bool enforce_item_restrictions = true, + bool enforce_ordering = true); bool needToSaveCOF(); void updateCOF(const LLUUID& category, bool append = false); void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append); @@ -68,6 +69,7 @@ public: LLInventoryModel::item_array_t& items_to_kill); void findAllExcessOrDuplicateItems(const LLUUID& cat_id, LLInventoryModel::item_array_t& items_to_kill); + void enforceCOFItemRestrictions(LLPointer cb); // Copy all items and the src category itself. void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id, @@ -190,7 +192,9 @@ public: //Check ordering information on wearables stored in links' descriptions and update if it is invalid // COF is processed if cat_id is not specified - void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null, bool update_base_outfit_ordering = false); + void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null, + bool update_base_outfit_ordering = false, + LLPointer cb = NULL); bool isOutfitLocked() { return mOutfitLocked; } @@ -263,7 +267,8 @@ class LLUpdateAppearanceOnDestroy: public LLInventoryCallback { public: LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering = false, - bool enforce_item_restrictions = true); + bool enforce_item_restrictions = true, + bool enforce_ordering = true); virtual ~LLUpdateAppearanceOnDestroy(); /* virtual */ void fire(const LLUUID& inv_item); @@ -271,6 +276,7 @@ private: U32 mFireCount; bool mUpdateBaseOrder; bool mEnforceItemRestrictions; + bool mEnforceOrdering; }; class LLUpdateAppearanceAndEditWearableOnDestroy: public LLInventoryCallback 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 { diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 515c99c0b4..fd2481b531 100755 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -340,7 +340,7 @@ public: void onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links = true); // Update model after an existing item gets updated on server. - void onItemUpdated(const LLUUID& item_id, const LLSD& updates); + void onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version); // Update model after an existing category gets updated on server. void onCategoryUpdated(const LLUUID& cat_id, const LLSD& updates); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 90fef3b5ed..62bcfd20a7 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -726,7 +726,9 @@ void LLViewerInventoryItem::packUpdateMessage(LLMessageSystem* msg, const LLSD& } if (updates.has("desc")) { - msg->addStringFast(_PREHASH_Description, updates["desc"].asString()); + std::string new_desc = updates["desc"].asString(); + LLInventoryItem::correctInventoryDescription(new_desc); + msg->addStringFast(_PREHASH_Description, new_desc); } else { @@ -1461,7 +1463,7 @@ void update_inventory_item( obj->packUpdateMessage(msg, updates); gAgent.sendReliableMessage(); - gInventory.onItemUpdated(item_id, updates); + gInventory.onItemUpdated(item_id, updates,false); if (cb) { cb->fire(item_id); -- cgit v1.2.3 From c498f53d9ab02a41886b55762883d116801fd39b Mon Sep 17 00:00:00 2001 From: "prep@lindenlab.com" Date: Tue, 28 May 2013 11:51:11 -0500 Subject: Sh-4035: Updated implementation according to new specs. Fixed a couple of outstanding bugs. --- indra/newview/llfloatersidepanelcontainer.cpp | 13 ++- indra/newview/llfloatersidepanelcontainer.h | 3 + indra/newview/llsidepanelappearance.cpp | 125 ++++++++++++--------- indra/newview/llsidepanelappearance.h | 14 ++- .../newview/skins/default/xui/en/notifications.xml | 30 ++++- 5 files changed, 122 insertions(+), 63 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index d5bb8157cf..13a9ba1695 100755 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -70,7 +70,16 @@ void LLFloaterSidePanelContainer::onOpen(const LLSD& key) { getChild(sMainPanelName)->onOpen(key); } - +void LLFloaterSidePanelContainer::onClose(bool app_quitting) +{ + mForceCloseAfterVerify = true; + LLSidepanelAppearance* panel = getSidePanelAppearance(); + if ( panel ) + { + panel->mRevertSet = true; + panel->onCloseFromAppearance( this ); + } +} void LLFloaterSidePanelContainer::onClickCloseBtn() { LLSidepanelAppearance* panel = getSidePanelAppearance(); @@ -127,7 +136,7 @@ void LLFloaterSidePanelContainer::showPanel(const std::string& floater_name, con { if ( panel->checkForDirtyEdits() ) { - panel->onClickConfirmExitWithoutSaveIntoAppearance(); + panel->onClickConfirmExitWithoutSaveIntoAppearance( floaterp ); } else { diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h index 974934b48f..dc85570f7e 100755 --- a/indra/newview/llfloatersidepanelcontainer.h +++ b/indra/newview/llfloatersidepanelcontainer.h @@ -44,6 +44,8 @@ class LLSidepanelAppearance; */ class LLFloaterSidePanelContainer : public LLFloater { + friend class LLSidePanelAppearance; + private: static const std::string sMainPanelName; @@ -52,6 +54,7 @@ public: ~LLFloaterSidePanelContainer(); /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void onClickCloseBtn(); /*virtual*/ BOOL postBuild(); void onConfirmationClose( const LLSD &confirm ); diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 858ed06544..70da576c83 100755 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -50,6 +50,7 @@ #include "llviewerwearable.h" #include "llnotificationsutil.h" #include "llfloatersidepanelcontainer.h" +#include "llviewerfoldertype.h" static LLRegisterPanelClassWrapper t_appearance("sidepanel_appearance"); @@ -85,58 +86,86 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaBack(const LLSD& notificat return false; } -bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notification, const LLSD& response) +void LLSidepanelAppearance::onCloseFromAppearance(LLFloaterSidePanelContainer* obj) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if ( option == 0 ) - { - //revert current edits - mEditWearable->revertChanges(); - //LLAppearanceMgr::getInstance()->wearBaseOutfit(); - toggleWearableEditPanel(FALSE); - LLVOAvatarSelf::onCustomizeEnd( FALSE ); - mLLFloaterSidePanelContainer->close(); - return true; - } - return false; -} - -void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaClose() -{ - if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !LLAppearanceMgr::getInstance()->isOutfitLocked() ) + mLLFloaterSidePanelContainer = obj; + if ( mEditWearable->isAvailable() && mEditWearable->isDirty() ) { LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this; LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) ); } else - { - showOutfitsInventoryPanel(); + { + LLVOAvatarSelf::onCustomizeEnd(FALSE); + toggleWearableEditPanel(FALSE); + mLLFloaterSidePanelContainer->mForceCloseAfterVerify=false; } } - - -bool LLSidepanelAppearance::callBackExitWithoutSaveIntoAppearance(const LLSD& notification, const LLSD& response) +bool LLSidepanelAppearance::onSaveCommit(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == option) + { + std::string outfit_name = response["message"].asString(); + LLStringUtil::trim(outfit_name); + std::string current_outfit_name; + + LLAppearanceMgr::getInstance()->getBaseOutfitName(current_outfit_name); + + if ( current_outfit_name == outfit_name ) + { + LLAppearanceMgr::getInstance()->updateBaseOutfit(); + } + else + { + LLUUID outfit_folder = LLAppearanceMgr::getInstance()->makeNewOutfitLinks( outfit_name,FALSE ); + } + + LLVOAvatarSelf::onCustomizeEnd( FALSE ); + mLLFloaterSidePanelContainer->close(); + } + + return false; +} +bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notification, const LLSD& response) +{ S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if ( option == 0 ) { - //revert current edits - mEditWearable->revertChanges(); - toggleWearableEditPanel(FALSE); + std::string outfit_name; + if (!LLAppearanceMgr::getInstance()->getBaseOutfitName(outfit_name)) + { + outfit_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_OUTFIT); + } + + LLSD args; + args["DESC"] = outfit_name; + + LLSD payload; + LLNotificationsUtil::add("SaveOutfitEither", args, payload, boost::bind(&LLSidepanelAppearance::onSaveCommit, this, _1, _2)); + showOutfitEditPanel(); + return false; + } + else if ( option == 1 ) + { + mEditWearable->revertChanges(); + toggleWearableEditPanel(FALSE); + showOutfitEditPanel(); LLVOAvatarSelf::onCustomizeEnd( FALSE ); - //mLLFloaterSidePanelContainer->close(); - showOutfitsInventoryPanel(); - return true; + mRevertSet = true; + return false; } + mLLFloaterSidePanelContainer->mForceCloseAfterVerify = false; + //mRevertSet = true; return false; } -void LLSidepanelAppearance::onClickConfirmExitWithoutSaveIntoAppearance() +void LLSidepanelAppearance::onClickConfirmExitWithoutSaveIntoAppearance( LLFloaterSidePanelContainer* obj ) { - if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !LLAppearanceMgr::getInstance()->isOutfitLocked() ) + mLLFloaterSidePanelContainer = obj; + if ( LLAppearanceMgr::getInstance()->isOutfitDirty() || mEditWearable->isDirty() ) { LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this; - LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveIntoAppearance,pSelf,_1,_2) ); + LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) ); } else { @@ -145,33 +174,19 @@ void LLSidepanelAppearance::onClickConfirmExitWithoutSaveIntoAppearance() } void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack() { - /* - if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !mSidePanelJustOpened && !LLAppearanceMgr::getInstance()->isOutfitLocked() ) - { - LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this; - LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaBack,pSelf,_1,_2) ); - } - else - */ - { - showOutfitsInventoryPanel(); - } + showOutfitsInventoryPanel(); } void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj) -{ - mLLFloaterSidePanelContainer = obj; - if ( /*LLAppearanceMgr::getInstance()->isOutfitDirty() && */ - /*!LLAppearanceMgr::getInstance()->isOutfitLocked() ||*/ - ( mEditWearable->isAvailable() && mEditWearable->isDirty() ) ) +{ mLLFloaterSidePanelContainer = obj; + if ( mEditWearable->isAvailable() && mEditWearable->isDirty() ) { LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this; LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) ); } else - { + { LLVOAvatarSelf::onCustomizeEnd(FALSE); - toggleWearableEditPanel(FALSE); mLLFloaterSidePanelContainer->close(); } } @@ -183,7 +198,8 @@ LLSidepanelAppearance::LLSidepanelAppearance() : mOutfitEdit(NULL), mCurrOutfitPanel(NULL), mOpened(false), - mSidePanelJustOpened(true) + mSidePanelJustOpened(true), + mRevertSet(false) { LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); outfit_observer.addBOFReplacedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); @@ -264,11 +280,15 @@ void LLSidepanelAppearance::onOpen(const LLSD& key) { // No specific panel requested. // If we're opened for the first time then show My Outfits. - // Else do nothing. + // Else show outfit edit panel if (!mOpened) { showOutfitsInventoryPanel(); } + else + { + showOutfitEditPanel(); + } } else { @@ -665,3 +685,4 @@ bool LLSidepanelAppearance::checkForDirtyEdits() { return ( mEditWearable->isDirty() ) ? true : false; } + diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h index caf5be62e9..5042e92f4b 100755 --- a/indra/newview/llsidepanelappearance.h +++ b/indra/newview/llsidepanelappearance.h @@ -50,7 +50,8 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); - void onClose(LLFloaterSidePanelContainer* obj); + /*virtual*/ void onClose(LLFloaterSidePanelContainer* obj); + void onClickCloseBtn(); void refreshCurrentOutfitName(const std::string& name = ""); @@ -72,10 +73,9 @@ public: bool callBackExitWithoutSaveViaBack(const LLSD& notification, const LLSD& response); void onClickConfirmExitWithoutSaveViaBack(); bool callBackExitWithoutSaveViaClose(const LLSD& notification, const LLSD& response); - void onClickConfirmExitWithoutSaveViaClose(); bool checkForDirtyEdits(); - bool callBackExitWithoutSaveIntoAppearance(const LLSD& notification, const LLSD& response); - void onClickConfirmExitWithoutSaveIntoAppearance(); + void onClickConfirmExitWithoutSaveIntoAppearance(LLFloaterSidePanelContainer* obj); + void onCloseFromAppearance(LLFloaterSidePanelContainer* obj); private: void onFilterEdit(const std::string& search_string); @@ -88,6 +88,9 @@ private: void toggleOutfitEditPanel(BOOL visible, BOOL disable_camera_switch = FALSE); void toggleWearableEditPanel(BOOL visible, LLViewerWearable* wearable = NULL, BOOL disable_camera_switch = FALSE); + + bool onSaveCommit(const LLSD& notification, const LLSD& response); + LLFilterEditor* mFilterEditor; LLPanelOutfitsInventory* mPanelOutfitsInventory; LLPanelOutfitEdit* mOutfitEdit; @@ -115,6 +118,9 @@ private: bool mSidePanelJustOpened; LLFloaterSidePanelContainer* mLLFloaterSidePanelContainer; +public: + + bool mRevertSet; }; #endif //LL_LLSIDEPANELAPPEARANCE_H diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 07c8ecc4dd..860dabdcc8 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -10118,13 +10118,33 @@ Cannot create large prims that intersect other players. Please re-try when othe icon="alertmodal.tga" name="ConfirmExitWithoutSave" type="alertmodal"> - Closing this window will discard any changes you have made. + You have not saved the changes to your outfit. Would you like to save it now? confirm + name="yesnocancelbuttons" + notext="Revert" + yestext="Yes" + canceltext="Dismiss"/> + + + + + Save outfit (defaults to current outfit): + confirm +
+ + [DESC] + +