Fix issue with persistent notifications. open_notifications.xml was accumulating inaccessible notifications. Added MaxPersistentNotifications to cap notifications. Notifications new stored per account per grid. Startup should be faster too.

This commit is contained in:
Shyotl
2020-05-09 04:50:01 -05:00
parent 3c3d8c2400
commit 61f90c665a
5 changed files with 99 additions and 42 deletions

View File

@@ -74,8 +74,9 @@ private:
bool historyHandler(const LLSD& payload) bool historyHandler(const LLSD& payload)
{ {
// we ignore "load" messages, but rewrite the persistence file on any other // we ignore "load" messages, but rewrite the persistence file on any other
// onDelete handes "delete" message, so skip that too.
std::string sigtype = payload["sigtype"]; std::string sigtype = payload["sigtype"];
if (sigtype != "load") if (sigtype != "load" && sigtype != "delete")
{ {
savePersistentNotifications(); savePersistentNotifications();
} }
@@ -85,11 +86,15 @@ private:
// The history channel gets all notifications except those that have been cancelled // The history channel gets all notifications except those that have been cancelled
static bool historyFilter(LLNotificationPtr pNotification) static bool historyFilter(LLNotificationPtr pNotification)
{ {
return !pNotification->isCancelled(); return pNotification->isPersistent() && !pNotification->isCancelled() && !pNotification->isRespondedTo() && !pNotification->isExpired();
} }
void savePersistentNotifications() void savePersistentNotifications()
{ {
if (mLoading)
{
return;
}
LL_INFOS() << "Saving open notifications to " << mFileName << LL_ENDL; LL_INFOS() << "Saving open notifications to " << mFileName << LL_ENDL;
llofstream notify_file(mFileName.c_str()); llofstream notify_file(mFileName.c_str());
@@ -104,6 +109,9 @@ private:
LLSD& data = output["data"]; LLSD& data = output["data"];
AILOCK_mItems; AILOCK_mItems;
static LLCachedControl<S32> maxPersistentNotificaitons("MaxPersistentNotifications");
for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it) for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it)
{ {
if (!LLNotificationTemplates::instance().templateExists((*it)->getName())) continue; if (!LLNotificationTemplates::instance().templateExists((*it)->getName())) continue;
@@ -111,7 +119,15 @@ private:
// only store notifications flagged as persisting // only store notifications flagged as persisting
LLNotificationTemplatePtr templatep = LLNotificationTemplates::instance().getTemplate((*it)->getName()); LLNotificationTemplatePtr templatep = LLNotificationTemplates::instance().getTemplate((*it)->getName());
if (!templatep->mPersist) continue; if (!templatep->mPersist) continue;
if ((*it)->isCancelled() || (*it)->isExpired() || (*it)->isRespondedTo()) continue;
if (data.size() >= maxPersistentNotificaitons)
{
LL_WARNS() << "Too many persistent notifications."
<< " Saved " << maxPersistentNotificaitons << " of " << mItems.size()
<< " persistent notifications." << LL_ENDL;
break;
}
data.append((*it)->asLLSD()); data.append((*it)->asLLSD());
} }
@@ -121,53 +137,75 @@ private:
void loadPersistentNotifications() void loadPersistentNotifications()
{ {
if (mLoading)
{
return;
}
mLoading = true;
LL_INFOS() << "Loading open notifications from " << mFileName << LL_ENDL; LL_INFOS() << "Loading open notifications from " << mFileName << LL_ENDL;
llifstream notify_file(mFileName.c_str()); while (true)
if (!notify_file.is_open())
{ {
LL_WARNS() << "Failed to open " << mFileName << LL_ENDL; llifstream notify_file(mFileName.c_str());
return; if (!notify_file.is_open())
} {
LL_WARNS() << "Failed to open " << mFileName << LL_ENDL;
break;
}
LLSD input; LLSD input;
LLPointer<LLSDParser> parser = new LLSDXMLParser(); LLPointer<LLSDParser> parser = new LLSDXMLParser();
if (parser->parse(notify_file, input, LLSDSerialize::SIZE_UNLIMITED) < 0) if (parser->parse(notify_file, input, LLSDSerialize::SIZE_UNLIMITED) < 0)
{ {
LL_WARNS() << "Failed to parse open notifications" << LL_ENDL; LL_WARNS() << "Failed to parse open notifications" << LL_ENDL;
return; break;
} }
if (input.isUndefined()) return; if (input.isUndefined()) return;
std::string version = input["version"]; std::string version = input["version"];
if (version != NOTIFICATION_PERSIST_VERSION) if (version != NOTIFICATION_PERSIST_VERSION)
{ {
LL_WARNS() << "Bad open notifications version: " << version << LL_ENDL; LL_WARNS() << "Bad open notifications version: " << version << LL_ENDL;
return; break;
} }
LLSD& data = input["data"]; LLSD& data = input["data"];
if (data.isUndefined()) return; if (data.isUndefined()) break;
LLNotifications& instance = LLNotifications::instance(); S32 processed_notifications = 0;
for (LLSD::array_const_iterator notification_it = data.beginArray(); static LLCachedControl<S32> maxPersistentNotificaitons("MaxPersistentNotifications");
notification_it != data.endArray();
++notification_it) LLNotifications& instance = LLNotifications::instance();
{ for (LLSD::array_const_iterator notification_it = data.beginArray();
instance.add(LLNotificationPtr(new LLNotification(*notification_it))); notification_it != data.endArray();
++notification_it)
{
if (processed_notifications++ >= maxPersistentNotificaitons)
{
LL_WARNS() << "Too many persistent notifications."
<< " Processed " << maxPersistentNotificaitons << " of " << data.size() << " persistent notifications." << LL_ENDL;
break;
}
instance.add(LLNotificationPtr(new LLNotification(*notification_it)));
}
break;
} }
mLoading = false;
savePersistentNotifications();
} }
//virtual //virtual
void onDelete(LLNotificationPtr pNotification) void onDelete(LLNotificationPtr pNotification)
{ {
// we want to keep deleted notifications in our log {
AILOCK_mItems; AILOCK_mItems;
mItems.insert(pNotification); mItems.erase(pNotification); // Delete immediately.
}
return; savePersistentNotifications();
} }
private: private:
bool mLoading = false;
std::string mFileName; std::string mFileName;
}; };
@@ -277,6 +315,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLXMLNodeP
} }
LLNotificationForm::LLNotificationForm(const LLSD& sd) LLNotificationForm::LLNotificationForm(const LLSD& sd)
: mIgnore(IGNORE_NO)
{ {
if (sd.isArray()) if (sd.isArray())
{ {
@@ -904,9 +943,9 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt
// if we have it in our list, pass on the delete, then delete it, else do nothing // if we have it in our list, pass on the delete, then delete it, else do nothing
if (wasFound) if (wasFound)
{ {
onDelete(pNotification);
abortProcessing = mChanged(payload); abortProcessing = mChanged(payload);
mItems.erase(pNotification); mItems.erase(pNotification);
onDelete(pNotification);
} }
} }
return abortProcessing; return abortProcessing;
@@ -1146,13 +1185,6 @@ void LLNotifications::createDefaultChannels()
LLNotificationChannel::buildChannel("Visible", "Ignore", LLNotificationChannel::buildChannel("Visible", "Ignore",
&LLNotificationFilters::includeEverything); &LLNotificationFilters::includeEverything);
// create special history channel
//std::string notifications_log_file = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml" );
// use ^^^ when done debugging notifications serialization
std::string notifications_log_file = gDirUtilp->getExpandedFilename ( LL_PATH_USER_SETTINGS, "open_notifications.xml" );
// this isn't a leak, don't worry about the empty "new"
new LLNotificationHistoryChannel(notifications_log_file);
// connect action methods to these channels // connect action methods to these channels
LLNotifications::instance().getChannel("Expiration")-> LLNotifications::instance().getChannel("Expiration")->
connectChanged(boost::bind(&LLNotifications::expirationHandler, this, _1)); connectChanged(boost::bind(&LLNotifications::expirationHandler, this, _1));
@@ -1164,6 +1196,14 @@ void LLNotifications::createDefaultChannels()
connectFailedFilter(&handleIgnoredNotification); connectFailedFilter(&handleIgnoredNotification);
} }
void LLNotifications::onLoginCompleted()
{
// create special history channel
std::string notifications_log_file = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, "singu_open_notifications_" + gHippoGridManager->getCurrentGrid()->getGridName() + ".xml");
// this isn't a leak, don't worry about the empty "new"
new LLNotificationHistoryChannel(notifications_log_file );
}
static std::string sStringSkipNextTime("Skip this dialog next time"); static std::string sStringSkipNextTime("Skip this dialog next time");
static std::string sStringAlwaysChoose("Always choose this option"); static std::string sStringAlwaysChoose("Always choose this option");

View File

@@ -796,6 +796,7 @@ public:
// OK to call more than once because it will reload // OK to call more than once because it will reload
bool loadNotifications(); bool loadNotifications();
void createDefaultChannels(); void createDefaultChannels();
void onLoginCompleted();
// we provide a collection of simple add notification functions so that it's reasonable to create notifications in one line // we provide a collection of simple add notification functions so that it's reasonable to create notifications in one line
LLNotificationPtr add(const std::string& name, LLNotificationPtr add(const std::string& name,

View File

@@ -10576,6 +10576,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<real>1.6</real> <real>1.6</real>
</map> </map>
<key>MaxPersistentNotifications</key>
<map>
<key>Comment</key>
<string>Maximum amount of persistent notifications</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<real>250</real>
</map>
<key>MaxSelectDistance</key> <key>MaxSelectDistance</key>
<map> <map>
<key>Comment</key> <key>Comment</key>

View File

@@ -5084,6 +5084,10 @@ void LLAppViewer::handleLoginComplete()
} }
mOnLoginCompleted(); mOnLoginCompleted();
// Singu Note: This would usually be registered via mOnLoginCompleted, but that would require code in newview regardless so.. just call directly here.
LLNotifications::instance().onLoginCompleted();
// Singu Note: Due to MAINT-4001, we must do this here, it lives in LLSidepanelInventory::updateInbox upstream. // Singu Note: Due to MAINT-4001, we must do this here, it lives in LLSidepanelInventory::updateInbox upstream.
// Consolidate Received items // Consolidate Received items
// We shouldn't have to do that but with a client/server system relying on a "well known folder" convention, // We shouldn't have to do that but with a client/server system relying on a "well known folder" convention,

View File

@@ -553,6 +553,7 @@ BOOL LLNotifyBox::tick()
{ {
if (mIsTip) if (mIsTip)
{ {
LLNotifications::instance().cancel(mNotification);
close(); close();
} }
return FALSE; return FALSE;