diff options
| author | Rider Linden <rider@lindenlab.com> | 2015-06-23 11:58:15 -0700 | 
|---|---|---|
| committer | Rider Linden <rider@lindenlab.com> | 2015-06-23 11:58:15 -0700 | 
| commit | ed4099628c362cdc880962198a2a4984ab67dd8f (patch) | |
| tree | 693d13a10eec3bd4c34b532772a130647e08ca94 | |
| parent | 1060094eec34dfd355e2995409cf37f3a84240d0 (diff) | |
Start work on coprocedure manager.
| -rwxr-xr-x | indra/newview/CMakeLists.txt | 2 | ||||
| -rwxr-xr-x | indra/newview/llassetuploadresponders.cpp | 3 | ||||
| -rwxr-xr-x | indra/newview/llassetuploadresponders.h | 2 | ||||
| -rw-r--r-- | indra/newview/llcoproceduremanager.cpp | 177 | ||||
| -rw-r--r-- | indra/newview/llcoproceduremanager.h | 118 | 
5 files changed, 301 insertions, 1 deletions
| diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 51787b6258..9b3324700a 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -164,6 +164,7 @@ set(viewer_SOURCE_FILES      llconversationloglistitem.cpp      llconversationmodel.cpp      llconversationview.cpp +    llcoproceduremanager.cpp      llcurrencyuimanager.cpp      llcylinder.cpp      lldateutil.cpp @@ -764,6 +765,7 @@ set(viewer_HEADER_FILES      llconversationloglistitem.h      llconversationmodel.h      llconversationview.h +    llcoproceduremanager.h      llcurrencyuimanager.h      llcylinder.h      lldateutil.h diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index d2b1dcbf35..e492b8cf5d 100755 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -674,6 +674,7 @@ void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content)  } +#if 0  /////////////////////////////////////////////////////  // LLNewAgentInventoryVariablePriceResponder::Impl //  ///////////////////////////////////////////////////// @@ -1144,5 +1145,5 @@ void LLNewAgentInventoryVariablePriceResponder::showConfirmationDialog(  				LLPointer<LLNewAgentInventoryVariablePriceResponder>(this)));  	}  } - +#endif diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index 7fbebc7481..18968bb1af 100755 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -79,6 +79,7 @@ protected:  	virtual void httpFailure();  }; +#if 0  // A base class which goes through and performs some default  // actions for variable price uploads.  If more specific actions  // are needed (such as different confirmation messages, etc.) @@ -115,6 +116,7 @@ private:  	class Impl;  	Impl* mImpl;  }; +#endif  class LLUpdateAgentInventoryResponder : public LLAssetUploadResponder  { diff --git a/indra/newview/llcoproceduremanager.cpp b/indra/newview/llcoproceduremanager.cpp new file mode 100644 index 0000000000..3f5fe7a582 --- /dev/null +++ b/indra/newview/llcoproceduremanager.cpp @@ -0,0 +1,177 @@ +/** +* @file llupdloadmanager.cpp +* @author Rider Linden +* @brief Singleton class for managing asset uploads to the sim. +* +* $LicenseInfo:firstyear=2015&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2015, 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 "linden_common.h"  + +#include "llviewercontrol.h" + +#include "llcoproceduremanager.h" + +//========================================================================= +#define COROCOUNT 1 + +//========================================================================= +LLCoprocedureManager::LLCoprocedureManager(): +    LLSingleton<LLCoprocedureManager>(), +    mPendingCoprocs(), +    mShutdown(false), +    mWakeupTrigger("CoprocedureManager", true), +    mCoroMapping(), +    mHTTPPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID) +{ +    initializeManager(); +} + +LLCoprocedureManager::~LLCoprocedureManager()  +{ +    shutdown(); +} + +//========================================================================= +void LLCoprocedureManager::initializeManager() +{ +    mShutdown = false; + +    // *TODO: Retrieve the actual number of concurrent coroutines fro gSavedSettings and +    // clamp to a "reasonable" number. +    for (int count = 0; count < COROCOUNT; ++count) +    { +        LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter = +            LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t( +            new LLCoreHttpUtil::HttpCoroutineAdapter("uploadPostAdapter", mHTTPPolicy)); + +        std::string uploadCoro = LLCoros::instance().launch("LLCoprocedureManager::coprocedureInvokerCoro", +            boost::bind(&LLCoprocedureManager::coprocedureInvokerCoro, this, _1, httpAdapter)); + +        mCoroMapping.insert(CoroAdapterMap_t::value_type(uploadCoro, httpAdapter)); +    } + +    mWakeupTrigger.post(LLSD()); +} + +void LLCoprocedureManager::shutdown(bool hardShutdown) +{ +    CoroAdapterMap_t::iterator it; + +    for (it = mCoroMapping.begin(); it != mCoroMapping.end(); ++it) +    { +        if (!(*it).first.empty()) +        { +            if (hardShutdown) +            { +                LLCoros::instance().kill((*it).first); +            } +        } +        if ((*it).second) +        { +            (*it).second->cancelYieldingOperation(); +        } +    } + +    mShutdown = true; +    mCoroMapping.clear(); +    mPendingCoprocs.clear(); +} + +//========================================================================= +LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &name, LLCoprocedureManager::CoProcedure_t proc) +{ +    LLUUID id(LLUUID::generateNewID()); + +    mPendingCoprocs.push_back(QueuedCoproc::ptr_t(new QueuedCoproc(name, id, proc))); +    LL_INFOS() << "Coprocedure(" << name << ") enqueued with id=" << id.asString() << LL_ENDL; + +    mWakeupTrigger.post(LLSD()); + +    return id; +} + +void LLCoprocedureManager::cancelCoprocedure(const LLUUID &id) +{ +    // first check the active coroutines.  If there, remove it and return. +    ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(id); +    if (itActive != mActiveCoprocs.end()) +    { +        LL_INFOS() << "Found and canceling active coprocedure with id=" << id.asString() << LL_ENDL; +        (*itActive).second->cancelYieldingOperation(); +        mActiveCoprocs.erase(itActive); +        return; +    } + +    for (AssetQueue_t::iterator it = mPendingCoprocs.begin(); it != mPendingCoprocs.end(); ++it) +    { +        if ((*it)->mId == id) +        { +            LL_INFOS() << "Found and removing queued coroutine(" << (*it)->mName << ") with Id=" << id.asString() << LL_ENDL; +            mPendingCoprocs.erase(it); +            return; +        } +    } + +    LL_INFOS() << "Coprocedure with Id=" << id.asString() << " was not found." << LL_ENDL; +} + +//========================================================================= +void LLCoprocedureManager::coprocedureInvokerCoro(LLCoros::self& self, LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter) +{ +    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + +    while (!mShutdown) +    { +        waitForEventOn(self, mWakeupTrigger); +        if (mShutdown) +            break; +         +        while (!mPendingCoprocs.empty()) +        { +            QueuedCoproc::ptr_t coproc = mPendingCoprocs.front(); +            mPendingCoprocs.pop_front(); +            mActiveCoprocs.insert(ActiveCoproc_t::value_type(coproc->mId, httpAdapter)); + +            LL_INFOS() << "Dequeued and invoking coprocedure(" << coproc->mName << ") with id=" << coproc->mId.asString() << LL_ENDL; + +            try +            { +                coproc->mProc(self, httpAdapter, coproc->mId); +            } +            catch (std::exception &e) +            { +                LL_WARNS() << "Coprocedure(" << coproc->mName << ") id=" << coproc->mId.asString() << +                    " threw an exception! Message=\"" << e.what() << "\"" << LL_ENDL; +            } + +            LL_INFOS() << "Finished coprocedure(" << coproc->mName << ")" << LL_ENDL; + +            ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(coproc->mId); +            if (itActive != mActiveCoprocs.end()) +            { +                mActiveCoprocs.erase(itActive); +            } +        } +    } +} diff --git a/indra/newview/llcoproceduremanager.h b/indra/newview/llcoproceduremanager.h new file mode 100644 index 0000000000..8902b217c2 --- /dev/null +++ b/indra/newview/llcoproceduremanager.h @@ -0,0 +1,118 @@ +/** +* @file llupdloadmanager.h +* @author Rider Linden +* @brief Singleton class for managing asset uploads to the sim. +* +* $LicenseInfo:firstyear=2015&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2015, 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_UPLOAD_MANAGER_H +#define LL_UPLOAD_MANAGER_H + +#include "lleventcoro.h" +#include "llcoros.h" +#include "llcorehttputil.h" +#include "lluuid.h" + +class LLCoprocedureManager : public LLSingleton < LLCoprocedureManager > +{ +public: +    typedef boost::function<void(LLCoros::self &, LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, const LLUUID &id)> CoProcedure_t; + +    virtual ~LLCoprocedureManager(); + +    /// Places the coprocedure on the queue for processing.  +    ///  +    /// @param name Is used for debugging and should identify this coroutine. +    /// @param proc Is a bound function to be executed  +    ///  +    /// @return This method returns a UUID that can be used later to cancel execution. +    LLUUID enqueueCoprocedure(const std::string &name, CoProcedure_t proc); + +    /// Cancel a coprocedure. If the coprocedure is already being actively executed  +    /// this method calls cancelYieldingOperation() on the associated HttpAdapter +    /// If it has not yet been dequeued it is simply removed from the queue. +    void cancelCoprocedure(const LLUUID &id); + +    /// Requests a shutdown of the upload manager. Passing 'true' will perform  +    /// an immediate kill on the upload coroutine. +    void shutdown(bool hardShutdown = false); + +    /// Returns the number of coprocedures in the queue awaiting processing. +    /// +    inline size_t countPending() const +    { +        return mPendingCoprocs.size(); +    } + +    /// Returns the number of coprocedures actively being processed. +    /// +    inline size_t countActive() const +    { +        return mActiveCoprocs.size(); +    } + +    /// Returns the total number of coprocedures either queued or in active processing. +    /// +    inline size_t count() const +    { +        return countPending() + countActive(); +    } + +protected: +    LLCoprocedureManager(); + +private: +    struct QueuedCoproc +    { +        typedef boost::shared_ptr<QueuedCoproc> ptr_t; + +        QueuedCoproc(const std::string &name, const LLUUID &id, CoProcedure_t proc): +            mName(name), +            mId(id), +            mProc(proc) +        {} + +        std::string mName; +        LLUUID mId; +        CoProcedure_t mProc; +    }; +     +    typedef std::deque<QueuedCoproc::ptr_t>  AssetQueue_t; +    typedef std::map<LLUUID, LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t> ActiveCoproc_t; + +    AssetQueue_t    mPendingCoprocs; +    ActiveCoproc_t  mActiveCoprocs; +    bool            mShutdown; +    LLEventStream   mWakeupTrigger; + + +    typedef std::map<std::string, LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t> CoroAdapterMap_t; +    LLCore::HttpRequest::policy_t mHTTPPolicy; + +    CoroAdapterMap_t mCoroMapping; + +    void initializeManager(); +    void coprocedureInvokerCoro(LLCoros::self& self, LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter); +}; + +#endif | 
