diff options
Diffstat (limited to 'indra/newview/llnotificationstorage.cpp')
-rw-r--r-- | indra/newview/llnotificationstorage.cpp | 246 |
1 files changed, 66 insertions, 180 deletions
diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index 4cad96fdc7..b6184f09bf 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -25,225 +25,111 @@ */ #include "llviewerprecompiledheaders.h" // must be first include + #include "llnotificationstorage.h" -#include "llxmlnode.h" // for linux compilers +#include <string> +#include <map> -#include "llchannelmanager.h" -#include "llscreenchannel.h" -#include "llscriptfloater.h" +#include "llerror.h" +#include "llfile.h" +#include "llnotifications.h" +#include "llpointer.h" +#include "llsd.h" #include "llsdserialize.h" -#include "llviewermessage.h" +#include "llsingleton.h" +#include "llregistry.h" +#include "llviewermessage.h" -////////////////////////////////////////////////////////////////////////// +typedef boost::function<LLNotificationResponderInterface * (const LLSD& pParams)> responder_constructor_t; -class LLResponderRegistry +class LLResponderRegistry : public LLRegistrySingleton<std::string, responder_constructor_t, LLResponderRegistry> { -public: - - static void registerResponders(); - - static LLNotificationResponderInterface* createResponder(const std::string& notification_name, const LLSD& params); - -private: - - template<typename RESPONDER_TYPE> - static LLNotificationResponderInterface* create(const LLSD& params) - { - RESPONDER_TYPE* responder = new RESPONDER_TYPE(); - responder->fromLLSD(params); - return responder; - } - - typedef boost::function<LLNotificationResponderInterface* (const LLSD& params)> responder_constructor_t; + public: + template<typename RESPONDER_TYPE> static LLNotificationResponderInterface * create(const LLSD& pParams); + LLNotificationResponderInterface * createResponder(const std::string& pNotificationName, const LLSD& pParams); +}; - static void add(const std::string& notification_name, const responder_constructor_t& ctr); +template<typename RESPONDER_TYPE> LLNotificationResponderInterface * LLResponderRegistry::create(const LLSD& pParams) +{ + RESPONDER_TYPE* responder = new RESPONDER_TYPE(); + responder->fromLLSD(pParams); + return responder; +} -private: - typedef std::map<std::string, responder_constructor_t> build_map_t; +LLNotificationResponderInterface * LLResponderRegistry::createResponder(const std::string& pNotificationName, const LLSD& pParams) +{ + responder_constructor_t * factoryFunc = (LLResponderRegistry::getValue(pNotificationName)); + + if(factoryFunc) + { + return (*factoryFunc)(pParams); + } + + return NULL; +} - static build_map_t sBuildMap; -}; +LLResponderRegistry::StaticRegistrar sRegisterObjectGiveItem("ObjectGiveItem", &LLResponderRegistry::create<LLOfferInfo>); +LLResponderRegistry::StaticRegistrar sRegisterUserGiveItem("UserGiveItem", &LLResponderRegistry::create<LLOfferInfo>); +LLResponderRegistry::StaticRegistrar sRegisterOfferInfo("offer_info", &LLResponderRegistry::create<LLOfferInfo>); -////////////////////////////////////////////////////////////////////////// -LLPersistentNotificationStorage::LLPersistentNotificationStorage() +LLNotificationStorage::LLNotificationStorage(std::string pFileName) + : mFileName(pFileName) { - mFileName = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml" ); } -bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& payload) +LLNotificationStorage::~LLNotificationStorage() { - // we ignore "load" messages, but rewrite the persistence file on any other - const std::string sigtype = payload["sigtype"].asString(); - if ("load" != sigtype) - { - saveNotifications(); - } - return false; } -// Storing or loading too many persistent notifications will severely hurt -// viewer load times, possibly to the point of failing to log in. Example case -// from MAINT-994 is 821 notifications. -static const S32 MAX_PERSISTENT_NOTIFICATIONS = 250; - -void LLPersistentNotificationStorage::saveNotifications() +bool LLNotificationStorage::writeNotifications(const LLSD& pNotificationData) const { - // TODO - think about save optimization. - llofstream notify_file(mFileName.c_str()); - if (!notify_file.is_open()) + llofstream notifyFile(mFileName.c_str()); + bool didFileOpen = notifyFile.is_open(); + + if (!didFileOpen) { - llwarns << "Failed to open " << mFileName << llendl; - return; + LL_WARNS("LLNotificationStorage") << "Failed to open file '" << mFileName << "'" << LL_ENDL; } - - LLSD output; - LLSD& data = output["data"]; - - LLNotificationChannelPtr history_channel = LLNotifications::instance().getChannel("Persistent"); - LLNotificationSet::iterator it = history_channel->begin(); - - for ( ; history_channel->end() != it; ++it) + else { - LLNotificationPtr notification = *it; - - // After a notification was placed in Persist channel, it can become - // responded, expired or canceled - in this case we are should not save it - if(notification->isRespondedTo() || notification->isCancelled() - || notification->isExpired()) - { - continue; - } - - data.append(notification->asLLSD()); - - if (data.size() >= MAX_PERSISTENT_NOTIFICATIONS) - { - llwarns << "Too many persistent notifications." - << " Saved " << MAX_PERSISTENT_NOTIFICATIONS << " of " << history_channel->size() << " persistent notifications." << llendl; - break; - } + LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter(); + formatter->format(pNotificationData, notifyFile, LLSDFormatter::OPTIONS_PRETTY); } - LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter(); - formatter->format(output, notify_file, LLSDFormatter::OPTIONS_PRETTY); + return didFileOpen; } -void LLPersistentNotificationStorage::loadNotifications() +bool LLNotificationStorage::readNotifications(LLSD& pNotificationData) const { - LLResponderRegistry::registerResponders(); - - llifstream notify_file(mFileName.c_str()); - if (!notify_file.is_open()) - { - llwarns << "Failed to open " << mFileName << llendl; - return; - } + bool didFileRead; - LLSD input; - LLPointer<LLSDParser> parser = new LLSDXMLParser(); - if (parser->parse(notify_file, input, LLSDSerialize::SIZE_UNLIMITED) < 0) - { - llwarns << "Failed to parse open notifications" << llendl; - return; - } - - if (input.isUndefined()) - { - return; - } + pNotificationData.clear(); - LLSD& data = input["data"]; - if (data.isUndefined()) + llifstream notifyFile(mFileName.c_str()); + didFileRead = notifyFile.is_open(); + if (!didFileRead) { - return; + LL_WARNS("LLNotificationStorage") << "Failed to open file '" << mFileName << "'" << LL_ENDL; } - - using namespace LLNotificationsUI; - LLScreenChannel* notification_channel = dynamic_cast<LLScreenChannel*>(LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); - - LLNotifications& instance = LLNotifications::instance(); - S32 processed_notifications = 0; - for (LLSD::array_const_iterator notification_it = data.beginArray(); - notification_it != data.endArray(); - ++notification_it) + else { - LLSD notification_params = *notification_it; - - if (instance.templateExists(notification_params["name"].asString())) + LLPointer<LLSDParser> parser = new LLSDXMLParser(); + didFileRead = (parser->parse(notifyFile, pNotificationData, LLSDSerialize::SIZE_UNLIMITED) >= 0); + if (!didFileRead) { - LLNotificationPtr notification(new LLNotification(notification_params)); - - LLNotificationResponderPtr responder(LLResponderRegistry:: - createResponder(notification_params["name"], notification_params["responder"])); - notification->setResponseFunctor(responder); - - instance.add(notification); - - // hide script floaters so they don't confuse the user and don't overlap startup toast - LLScriptFloaterManager::getInstance()->setFloaterVisible(notification->getID(), false); - - if(notification_channel) - { - // hide saved toasts so they don't confuse the user - notification_channel->hideToast(notification->getID()); - } - } - else - { - llwarns << "Failed to find template for persistent notification " << notification_params["name"].asString() << llendl; - } - - ++processed_notifications; - if (processed_notifications >= MAX_PERSISTENT_NOTIFICATIONS) - { - llwarns << "Too many persistent notifications." - << " Processed " << MAX_PERSISTENT_NOTIFICATIONS << " of " << data.size() << " persistent notifications." << llendl; - break; + LL_WARNS("LLNotificationStorage") << "Failed to parse open notifications from file '" << mFileName + << "'" << LL_ENDL; } } - LLNotifications::instance().getChannel("Persistent")-> - connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1)); + return didFileRead; } -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLResponderRegistry::build_map_t LLResponderRegistry::sBuildMap; - -void LLResponderRegistry::registerResponders() +LLNotificationResponderInterface * LLNotificationStorage::createResponder(const std::string& pNotificationName, const LLSD& pParams) const { - sBuildMap.clear(); - - add("ObjectGiveItem", &create<LLOfferInfo>); - add("UserGiveItem", &create<LLOfferInfo>); + return LLResponderRegistry::getInstance()->createResponder(pNotificationName, pParams); } - -LLNotificationResponderInterface* LLResponderRegistry::createResponder(const std::string& notification_name, const LLSD& params) -{ - build_map_t::const_iterator it = sBuildMap.find(notification_name); - if(sBuildMap.end() == it) - { - return NULL; - } - responder_constructor_t ctr = it->second; - return ctr(params); -} - -void LLResponderRegistry::add(const std::string& notification_name, const responder_constructor_t& ctr) -{ - if(sBuildMap.find(notification_name) != sBuildMap.end()) - { - llwarns << "Responder is already registered : " << notification_name << llendl; - llassert(!"Responder already registered"); - } - sBuildMap[notification_name] = ctr; -} - -// EOF |