summaryrefslogtreecommitdiff
path: root/indra/newview/llgroupmgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llgroupmgr.cpp')
-rw-r--r--indra/newview/llgroupmgr.cpp296
1 files changed, 164 insertions, 132 deletions
diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp
index 100aacb8ac..d53b36e59f 100644
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -55,19 +55,8 @@
#include "llcorehttputil.h"
#include "lluiusage.h"
-
-#if LL_MSVC
-#pragma warning(push)
-// disable boost::lexical_cast warning
-#pragma warning (disable:4702)
-#endif
-
#include <boost/lexical_cast.hpp>
-#if LL_MSVC
-#pragma warning(pop) // Restore all warnings to the previous state
-#endif
-
const U32 MAX_CACHED_GROUPS = 20;
//
@@ -190,7 +179,7 @@ S32 LLGroupRoleData::getMembersInRole(uuid_vec_t members,
in_role_end = std::set_intersection(mMemberIDs.begin(), mMemberIDs.end(),
members.begin(), members.end(),
in_role.begin());
- return in_role_end - in_role.begin();
+ return (S32)(in_role_end - in_role.begin());
}
void LLGroupRoleData::addMember(const LLUUID& member)
@@ -806,7 +795,7 @@ void LLGroupMgrGroupData::banMemberById(const LLUUID& participant_uuid)
mPendingBanRequest = false;
- LLGroupMemberData* member_data = (*mi).second;
+ LLGroupMemberData* member_data = mi->second;
if (member_data && member_data->isInRole(mOwnerRole))
{
return; // can't ban group owner
@@ -832,8 +821,7 @@ void LLGroupMgrGroupData::banMemberById(const LLUUID& participant_uuid)
// LLGroupMgr
//
-LLGroupMgr::LLGroupMgr():
- mMemberRequestInFlight(false)
+LLGroupMgr::LLGroupMgr()
{
}
@@ -968,11 +956,11 @@ void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data)
LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id);
if (!group_datap || (group_datap->mMemberRequestID != request_id))
{
- LL_WARNS() << "processGroupMembersReply: Received incorrect (stale?) group or request id" << LL_ENDL;
+ LL_WARNS() << "Received incorrect (stale?) group or request id" << LL_ENDL;
return;
}
- msg->getS32(_PREHASH_GroupData, "MemberCount", group_datap->mMemberCount );
+ msg->getS32Fast(_PREHASH_GroupData, _PREHASH_MemberCount, group_datap->mMemberCount);
if (group_datap->mMemberCount > 0)
{
@@ -987,12 +975,12 @@ void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data)
{
LLUUID member_id;
- msg->getUUIDFast(_PREHASH_MemberData, _PREHASH_AgentID, member_id, i );
- msg->getS32(_PREHASH_MemberData, _PREHASH_Contribution, contribution, i);
- msg->getU64(_PREHASH_MemberData, "AgentPowers", agent_powers, i);
+ msg->getUUIDFast(_PREHASH_MemberData, _PREHASH_AgentID, member_id, i);
+ msg->getS32Fast(_PREHASH_MemberData, _PREHASH_Contribution, contribution, i);
+ msg->getU64Fast(_PREHASH_MemberData, _PREHASH_AgentPowers, agent_powers, i);
msg->getStringFast(_PREHASH_MemberData, _PREHASH_OnlineStatus, online_status, i);
- msg->getString(_PREHASH_MemberData, "Title", title, i);
- msg->getBOOL(_PREHASH_MemberData,"IsOwner",is_owner,i);
+ msg->getStringFast(_PREHASH_MemberData, _PREHASH_Title, title, i);
+ msg->getBOOLFast(_PREHASH_MemberData, _PREHASH_IsOwner, is_owner, i);
if (member_id.notNull())
{
@@ -1037,7 +1025,7 @@ void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data)
group_datap->mMemberVersion.generate();
- if (group_datap->mMembers.size() == (U32)group_datap->mMemberCount)
+ if (group_datap->mMembers.size() == (U32)group_datap->mMemberCount)
{
group_datap->mMemberDataComplete = true;
group_datap->mMemberRequestID.setNull();
@@ -1569,7 +1557,7 @@ void LLGroupMgr::addGroup(LLGroupMgrGroupData* group_datap)
{
// LRU: Remove the oldest un-observed group from cache until group size is small enough
- F32 oldest_access = LLFrameTimer::getTotalSeconds();
+ F32 oldest_access = (F32)LLFrameTimer::getTotalSeconds();
group_map_t::iterator oldest_gi = mGroups.end();
for (group_map_t::iterator gi = mGroups.begin(); gi != mGroups.end(); ++gi )
@@ -1678,13 +1666,12 @@ void LLGroupMgr::sendGroupRoleMembersRequest(const LLUUID& group_id)
if (group_datap->mRoleMembersRequestID.isNull())
{
// Don't send the request if we don't have all the member or role data
- if (!group_datap->isMemberDataComplete()
- || !group_datap->isRoleDataComplete())
+ if (!group_datap->isMemberDataComplete() || !group_datap->isRoleDataComplete())
{
// *TODO: KLW FIXME: Should we start a member or role data request?
LL_INFOS("GrpMgr") << " Pending: " << (group_datap->mPendingRoleMemberRequest ? "Y" : "N")
- << " MemberDataComplete: " << (group_datap->mMemberDataComplete ? "Y" : "N")
- << " RoleDataComplete: " << (group_datap->mRoleDataComplete ? "Y" : "N") << LL_ENDL;
+ << ", MemberDataComplete: " << (group_datap->mMemberDataComplete ? "Y" : "N")
+ << ", RoleDataComplete: " << (group_datap->mRoleDataComplete ? "Y" : "N") << LL_ENDL;
group_datap->mPendingRoleMemberRequest = true;
return;
}
@@ -1984,14 +1971,14 @@ void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id,
group_datap->mMemberVersion.generate();
}
-void LLGroupMgr::getGroupBanRequestCoro(std::string url, LLUUID groupId)
+void LLGroupMgr::getGroupBanRequestCoro(std::string url, LLUUID group_id)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("groupMembersRequest", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- std::string finalUrl = url + "?group_id=" + groupId.asString();
+ std::string finalUrl = url + "?group_id=" + group_id.asString();
LLSD result = httpAdapter->getAndSuspend(httpRequest, finalUrl);
@@ -2012,8 +1999,8 @@ void LLGroupMgr::getGroupBanRequestCoro(std::string url, LLUUID groupId)
}
}
-void LLGroupMgr::postGroupBanRequestCoro(std::string url, LLUUID groupId,
- U32 action, uuid_vec_t banList, bool update)
+void LLGroupMgr::postGroupBanRequestCoro(std::string url, LLUUID group_id,
+ U32 action, uuid_vec_t ban_list, bool update)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
@@ -2026,20 +2013,16 @@ void LLGroupMgr::postGroupBanRequestCoro(std::string url, LLUUID groupId,
httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
-
- std::string finalUrl = url + "?group_id=" + groupId.asString();
+ std::string finalUrl = url + "?group_id=" + group_id.asString();
LLSD postData = LLSD::emptyMap();
postData["ban_action"] = (LLSD::Integer)action;
// Add our list of potential banned residents to the list
postData["ban_ids"] = LLSD::emptyArray();
- LLSD banEntry;
- uuid_vec_t::const_iterator it = banList.begin();
- for (; it != banList.end(); ++it)
+ for (const LLUUID& ban_id : ban_list)
{
- banEntry = (*it);
- postData["ban_ids"].append(banEntry);
+ postData["ban_ids"].append(ban_id);
}
LL_WARNS() << "post: " << ll_pretty_print_sd(postData) << LL_ENDL;
@@ -2064,7 +2047,7 @@ void LLGroupMgr::postGroupBanRequestCoro(std::string url, LLUUID groupId,
if (update)
{
- getGroupBanRequestCoro(url, groupId);
+ getGroupBanRequestCoro(url, group_id);
}
}
@@ -2151,55 +2134,80 @@ void LLGroupMgr::processGroupBanRequest(const LLSD& content)
LLGroupMgr::getInstance()->notifyObservers(GC_BANLIST);
}
-void LLGroupMgr::groupMembersRequestCoro(std::string url, LLUUID groupId)
+void LLGroupMgr::groupMembersRequestCoro(std::string url, LLUUID group_id, U32 page_size, U32 page_start, U32 sort_column, bool sort_descending)
{
+ LL_INFOS("GrpMgr") << "group_id: '" << group_id << "'"
+ << ", page_size: " << page_size << ", page_start: " << page_start
+ << ", sort_column: " << sort_column << ", sort_descending: " << sort_descending << LL_ENDL;
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("groupMembersRequest", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+ LLSD postData = LLSD::emptyMap();
+ postData["group_id"] = group_id;
+
+ if (page_size)
+ {
+ postData["page_size"] = LLSD::Integer(page_size);
+ if (page_start)
+ {
+ postData["page_start"] = LLSD::Integer(page_start);
+ }
+ }
+
+ if (sort_column)
+ {
+ postData["sort_column"] = LLSD::Integer(sort_column);
+ if (sort_descending)
+ {
+ postData["sort_descending"] = 1;
+ }
+ }
mMemberRequestInFlight = true;
- LLSD postData = LLSD::emptyMap();
- postData["group_id"] = groupId;
+ LLSD response = httpAdapter->postAndSuspend(httpRequest, url, postData, httpOpts);
- LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData, httpOpts);
+ mMemberRequestInFlight = false;
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLSD httpResults = response.get(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
if (!status)
{
LL_WARNS("GrpMgr") << "Error receiving group member data " << LL_ENDL;
- mMemberRequestInFlight = false;
return;
}
- result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
- LLGroupMgr::processCapGroupMembersRequest(result);
- mMemberRequestInFlight = false;
+ response.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+ processCapGroupMembersResponse(response, url, page_size, page_start, sort_column, sort_descending);
}
-void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id)
+void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id, U32 page_size, U32 page_start, const std::string& sort_column_name, bool sort_descending)
{
static U32 lastGroupMemberRequestFrame = 0;
// Have we requested the information already this frame?
// Todo: make this per group, we can invite to one group and simultaneously be checking another one
- if ((lastGroupMemberRequestFrame == gFrameCount) || (mMemberRequestInFlight))
+ if ((lastGroupMemberRequestFrame == gFrameCount) || mMemberRequestInFlight)
return;
+ LL_INFOS("GrpMgr") << "group_id: '" << group_id << "'"
+ << ", page_size: " << page_size << ", page_start: " << page_start
+ << ", sort_column_name: '" << sort_column_name << "', sort_descending: " << sort_descending << LL_ENDL;
+
LLViewerRegion* currentRegion = gAgent.getRegion();
// Thank you FS:Ansariel!
- if(!currentRegion)
+ if (!currentRegion)
{
LL_WARNS("GrpMgr") << "Agent does not have a current region. Uh-oh!" << LL_ENDL;
return;
}
// Check to make sure we have our capabilities
- if(!currentRegion->capabilitiesReceived())
+ if (!currentRegion->capabilitiesReceived())
{
LL_WARNS("GrpMgr") << " Capabilities not received!" << LL_ENDL;
return;
@@ -2209,9 +2217,9 @@ void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id)
std::string cap_url = currentRegion->getCapability("GroupMemberData");
// Thank you FS:Ansariel!
- if(cap_url.empty())
+ if (cap_url.empty())
{
- LL_INFOS("GrpMgr") << "Region has no GroupMemberData capability. Falling back to UDP fetch." << LL_ENDL;
+ LL_INFOS("GrpMgr") << "Region has no GroupMemberData capability. Falling back to UDP fetch." << LL_ENDL;
sendGroupMembersRequest(group_id);
return;
}
@@ -2221,120 +2229,139 @@ void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id)
lastGroupMemberRequestFrame = gFrameCount;
- LLCoros::instance().launch("LLGroupMgr::groupMembersRequestCoro",
- boost::bind(&LLGroupMgr::groupMembersRequestCoro, this, cap_url, group_id));
-}
+ U32 sort_column = 0; // No sorting by default
+ if (!sort_column_name.empty())
+ {
+ static const std::vector<std::string> column_names = { "name", "donated", "online", "title" };
+ auto it = std::find(column_names.begin(), column_names.end(), sort_column_name);
+ if (it == column_names.end())
+ {
+ LL_WARNS("GrpMgr") << "Invalid column name: '" << sort_column_name << "'" << LL_ENDL;
+ }
+ else
+ {
+ // Use offset (1) because 0 means "no sorting"
+ sort_column = 1 + (U32)std::distance(column_names.begin(), it);
+ }
+ }
+ LLCoros::instance().launch("LLGroupMgr::groupMembersRequestCoro", [&]()
+ {
+ groupMembersRequestCoro(cap_url, group_id, page_size, page_start, sort_column, sort_descending);
+ });
+}
-void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
+void LLGroupMgr::processCapGroupMembersResponse(const LLSD& response, const std::string& url, U32 page_size, U32 page_start, U32 sort_column, bool sort_descending)
{
+ LLUUID group_id = response["group_id"].asUUID();
+ LL_INFOS("GrpMgr") << "group_id: '" << group_id << "'"
+ << ", page_size: " << page_size << ", page_start: " << page_start
+ << ", sort_column: " << sort_column << ", sort_descending: " << sort_descending << LL_ENDL;
+
// Did we get anything in content?
- if(!content.size())
+ if (!response.size())
{
- LL_DEBUGS("GrpMgr") << "No group member data received." << LL_ENDL;
+ LL_INFOS("GrpMgr") << "No group member data received." << LL_ENDL;
return;
}
- LLUUID group_id = content["group_id"].asUUID();
-
LLGroupMgrGroupData* group_datap = getGroupData(group_id);
- if(!group_datap)
+ if (!group_datap)
{
LL_WARNS("GrpMgr") << "Received incorrect, possibly stale, group or request id" << LL_ENDL;
return;
}
- // If we have no members, there's no reason to do anything else
- S32 num_members = content["member_count"];
- if (num_members < 1)
- {
- LL_INFOS("GrpMgr") << "Received empty group members list for group id: " << group_id.asString() << LL_ENDL;
- // Set mMemberDataComplete for correct handling of empty responses. See MAINT-5237
- group_datap->mMemberDataComplete = true;
- group_datap->mChanged = true;
- LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA);
- return;
- }
+ LLSD members = response["members"];
+ LLSD titles = response["titles"];
+ LLSD defaults = response["defaults"];
- group_datap->mMemberCount = num_members;
-
- LLSD member_list = content["members"];
- LLSD titles = content["titles"];
- LLSD defaults = content["defaults"];
-
- std::string online_status;
- std::string title;
- S32 contribution;
- U64 member_powers;
- // If this is changed to a bool, make sure to change the LLGroupMemberData constructor
- bool is_owner;
+ size_t members_before = group_datap->mMembers.size();
+ size_t members_loaded = members.size();
// Compute this once, rather than every time.
- U64 default_powers = llstrtou64(defaults["default_powers"].asString().c_str(), NULL, 16);
+ std::string default_title = titles.size() ? titles[0].asString() : LLStringUtil::null;
+ U64 default_powers = llstrtou64(defaults["default_powers"].asString().c_str(), NULL, 16);
- LLSD::map_const_iterator member_iter_start = member_list.beginMap();
- LLSD::map_const_iterator member_iter_end = member_list.endMap();
- for( ; member_iter_start != member_iter_end; ++member_iter_start)
+ auto members_end = members.endMap();
+ for (auto it = members.beginMap(); it != members_end; ++it)
{
// Reset defaults
- online_status = "unknown";
- title = titles[0].asString();
- contribution = 0;
- member_powers = default_powers;
- is_owner = false;
+ std::string online_status = "unknown";
+ std::string title = default_title;
+ U64 member_powers = default_powers;
+ S32 donated_square_meters = 0;
+ bool is_owner = false;
- const LLUUID member_id(member_iter_start->first);
- LLSD member_info = member_iter_start->second;
+ const LLUUID member_id(it->first);
+ LLSD member_info = it->second;
- if(member_info.has("last_login"))
+ if (member_info.has("last_login"))
{
online_status = member_info["last_login"].asString();
- if(online_status == "Online")
+ if (online_status == "Online")
+ {
online_status = LLTrans::getString("group_member_status_online");
+ }
else
+ {
formatDateString(online_status);
+ }
}
- if(member_info.has("title"))
+ if (member_info.has("title"))
+ {
title = titles[member_info["title"].asInteger()].asString();
+ }
- if(member_info.has("powers"))
+ if (member_info.has("powers"))
+ {
member_powers = llstrtou64(member_info["powers"].asString().c_str(), NULL, 16);
+ }
- if(member_info.has("donated_square_meters"))
- contribution = member_info["donated_square_meters"];
+ if (member_info.has("donated_square_meters"))
+ {
+ donated_square_meters = member_info["donated_square_meters"];
+ }
- if(member_info.has("owner"))
+ if (member_info.has("owner"))
+ {
is_owner = true;
+ }
LLGroupMemberData* data = new LLGroupMemberData(member_id,
- contribution,
- member_powers,
- title,
- online_status,
- is_owner);
-
- LLGroupMemberData* member_old = group_datap->mMembers[member_id];
- if (member_old && group_datap->mRoleMemberDataComplete)
- {
- LLGroupMemberData::role_list_t::iterator rit = member_old->roleBegin();
- LLGroupMemberData::role_list_t::iterator end = member_old->roleEnd();
+ donated_square_meters, member_powers, title, online_status, is_owner);
- for ( ; rit != end; ++rit)
+ if (group_datap->mRoleMemberDataComplete)
+ {
+ if (LLGroupMemberData* member_old = group_datap->mMembers[member_id])
{
- data->addRole((*rit).first,(*rit).second);
+ auto role_end = member_old->roleEnd();
+ for (auto role_it = member_old->roleBegin(); role_it != role_end; ++role_it)
+ {
+ data->addRole(role_it->first, role_it->second);
+ }
+ }
+ else
+ {
+ group_datap->mRoleMemberDataComplete = false;
}
- }
- else
- {
- group_datap->mRoleMemberDataComplete = false;
}
group_datap->mMembers[member_id] = data;
}
+ U32 member_count = (U32)group_datap->mMembers.size();
+
+ group_datap->mMemberCount = (S32)member_count;
+ group_datap->mMemberDataComplete = true;
+ group_datap->mMemberRequestID.setNull();
group_datap->mMemberVersion.generate();
+ LL_INFOS("GrpMgr") << "members before: " << members_before
+ << ", members loaded: " << members_loaded
+ << ", members now: " << member_count << LL_ENDL;
+
// Technically, we have this data, but to prevent completely overhauling
// this entire system (it would be nice, but I don't have the time),
// I'm going to be dumb and just call services I most likely don't need
@@ -2342,12 +2369,19 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
//
// TODO:
// Refactor to reduce multiple calls for data we already have.
- if(group_datap->mTitles.size() < 1)
+ if (group_datap->mTitles.size() < 1)
+ {
sendGroupTitlesRequest(group_id);
+ }
+ if (page_size && members_loaded >= page_size && member_count > members_before)
+ {
+ LLCoros::instance().launch("LLGroupMgr::groupMembersRequestCoro", [&]()
+ {
+ groupMembersRequestCoro(url, group_id, page_size, page_start, sort_column, sort_descending);
+ });
+ }
- group_datap->mMemberDataComplete = true;
- group_datap->mMemberRequestID.setNull();
// Make the role-member data request
if (group_datap->mPendingRoleMemberRequest || !group_datap->mRoleMemberDataComplete)
{
@@ -2357,10 +2391,8 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
group_datap->mChanged = true;
notifyObservers(GC_MEMBER_DATA);
-
}
-
void LLGroupMgr::sendGroupRoleChanges(const LLUUID& group_id)
{
LL_DEBUGS("GrpMgr") << "LLGroupMgr::sendGroupRoleChanges" << LL_ENDL;
@@ -2379,9 +2411,11 @@ void LLGroupMgr::sendGroupRoleChanges(const LLUUID& group_id)
void LLGroupMgr::cancelGroupRoleChanges(const LLUUID& group_id)
{
LL_DEBUGS("GrpMgr") << "LLGroupMgr::cancelGroupRoleChanges" << LL_ENDL;
- LLGroupMgrGroupData* group_datap = getGroupData(group_id);
- if (group_datap) group_datap->cancelRoleChanges();
+ if (LLGroupMgrGroupData* group_datap = getGroupData(group_id))
+ {
+ group_datap->cancelRoleChanges();
+ }
}
//static
@@ -2503,5 +2537,3 @@ void LLGroupMgr::debugClearAllGroups(void*)
LLGroupMgr::getInstance()->clearGroups();
LLGroupMgr::parseRoleActions("role_actions.xml");
}
-
-