summaryrefslogtreecommitdiff
path: root/indra/llmessage/llcachename.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage/llcachename.cpp')
-rw-r--r--indra/llmessage/llcachename.cpp527
1 files changed, 268 insertions, 259 deletions
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index 274bf5cc04..4a66a31c35 100644
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -2,30 +2,25 @@
* @file llcachename.cpp
* @brief A hierarchical cache of first and last names queried based on UUID.
*
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -41,11 +36,7 @@
#include "llsdserialize.h"
#include "lluuid.h"
#include "message.h"
-
-// Constants
-const char* CN_WAITING = "(waiting)";
-const char* CN_NOBODY = "(nobody)";
-const char* CN_NONE = "(none)";
+#include "llmemtype.h"
// llsd serialization constants
static const std::string AGENTS("agents");
@@ -64,6 +55,7 @@ const S32 CN_FILE_VERSION = 2;
// Globals
LLCacheName* gCacheName = NULL;
+std::map<std::string, std::string> LLCacheName::sCacheName;
/// ---------------------------------------------------------------------------
/// class LLCacheNameEntry
@@ -77,16 +69,17 @@ public:
public:
bool mIsGroup;
U32 mCreateTime; // unix time_t
- char mFirstName[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/
- char mLastName[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/
- char mGroupName[DB_GROUP_NAME_BUF_SIZE]; /*Flawfinder: ignore*/
+ // IDEVO TODO collapse names to one field, which will eliminate
+ // many string compares on "Resident"
+ std::string mFirstName;
+ std::string mLastName;
+ std::string mGroupName;
};
LLCacheNameEntry::LLCacheNameEntry()
+ : mIsGroup(false),
+ mCreateTime(0)
{
- mFirstName[0] = '\0';
- mLastName[0] = '\0';
- mGroupName[0] = '\0';
}
@@ -94,17 +87,19 @@ class PendingReply
{
public:
LLUUID mID;
- LLCacheNameCallback mCallback;
+ LLCacheNameSignal mSignal;
LLHost mHost;
- void* mData;
- PendingReply(const LLUUID& id, LLCacheNameCallback callback, void* data = NULL)
- : mID(id), mCallback(callback), mData(data)
- { }
-
+
PendingReply(const LLUUID& id, const LLHost& host)
- : mID(id), mCallback(0), mHost(host)
- { }
-
+ : mID(id), mHost(host)
+ {
+ }
+
+ boost::signals2::connection setCallback(const LLCacheNameCallback& cb)
+ {
+ return mSignal.connect(cb);
+ }
+
void done() { mID.setNull(); }
bool isDone() const { return mID.isNull() != FALSE; }
};
@@ -128,7 +123,7 @@ private:
};
ReplySender::ReplySender(LLMessageSystem* msg)
- : mMsg(msg), mPending(false)
+ : mMsg(msg), mPending(false), mCurrIsGroup(false)
{ }
ReplySender::~ReplySender()
@@ -189,10 +184,10 @@ void ReplySender::flush()
typedef std::set<LLUUID> AskQueue;
-typedef std::vector<PendingReply> ReplyQueue;
+typedef std::list<PendingReply*> ReplyQueue;
typedef std::map<LLUUID,U32> PendingQueue;
typedef std::map<LLUUID, LLCacheNameEntry*> Cache;
-typedef std::vector<LLCacheNameCallback> Observers;
+typedef std::map<std::string, LLUUID> ReverseCache;
class LLCacheName::Impl
{
@@ -202,7 +197,9 @@ public:
Cache mCache;
// the map of UUIDs to names
-
+ ReverseCache mReverseCache;
+ // map of names to UUIDs
+
AskQueue mAskNameQueue;
AskQueue mAskGroupQueue;
// UUIDs to ask our upstream host about
@@ -213,13 +210,18 @@ public:
ReplyQueue mReplyQueue;
// requests awaiting replies from us
- Observers mObservers;
+ LLCacheNameSignal mSignal;
LLFrameTimer mProcessTimer;
Impl(LLMessageSystem* msg);
~Impl();
+ BOOL getName(const LLUUID& id, std::string& first, std::string& last);
+
+ boost::signals2::connection addPending(const LLUUID& id, const LLCacheNameCallback& callback);
+ void addPending(const LLUUID& id, const LLHost& host);
+
void processPendingAsks();
void processPendingReplies();
void sendRequest(const char* msg_name, const AskQueue& queue);
@@ -233,8 +235,6 @@ public:
static void handleUUIDNameReply(LLMessageSystem* msg, void** userdata);
static void handleUUIDGroupNameRequest(LLMessageSystem* msg, void** userdata);
static void handleUUIDGroupNameReply(LLMessageSystem* msg, void** userdata);
-
- void notifyObservers(const LLUUID& id, const char* first, const char* last, BOOL group);
};
@@ -249,6 +249,9 @@ LLCacheName::LLCacheName(LLMessageSystem* msg)
LLCacheName::LLCacheName(LLMessageSystem* msg, const LLHost& upstream_host)
: impl(* new Impl(msg))
{
+ sCacheName["waiting"] = "(Loading...)";
+ sCacheName["nobody"] = "(nobody)";
+ sCacheName["none"] = "(none)";
setUpstream(upstream_host);
}
@@ -274,135 +277,37 @@ LLCacheName::Impl::Impl(LLMessageSystem* msg)
LLCacheName::Impl::~Impl()
{
for_each(mCache.begin(), mCache.end(), DeletePairedPointer());
+ for_each(mReplyQueue.begin(), mReplyQueue.end(), DeletePointer());
}
-
-void LLCacheName::setUpstream(const LLHost& upstream_host)
+boost::signals2::connection LLCacheName::Impl::addPending(const LLUUID& id, const LLCacheNameCallback& callback)
{
- impl.mUpstreamHost = upstream_host;
+ PendingReply* reply = new PendingReply(id, LLHost());
+ boost::signals2::connection res = reply->setCallback(callback);
+ mReplyQueue.push_back(reply);
+ return res;
}
-void LLCacheName::addObserver(LLCacheNameCallback callback)
+void LLCacheName::Impl::addPending(const LLUUID& id, const LLHost& host)
{
- impl.mObservers.push_back(callback);
+ PendingReply* reply = new PendingReply(id, host);
+ mReplyQueue.push_back(reply);
}
-void LLCacheName::removeObserver(LLCacheNameCallback callback)
-{
- Observers::iterator it = impl.mObservers.begin();
- Observers::iterator end = impl.mObservers.end();
-
- for ( ; it != end; ++it)
- {
- const LLCacheNameCallback& cb = (*it);
- if (cb == callback)
- {
- impl.mObservers.erase(it);
- return;
- }
- }
-}
-
-void LLCacheName::cancelCallback(const LLUUID& id, LLCacheNameCallback callback, void* user_data)
+void LLCacheName::setUpstream(const LLHost& upstream_host)
{
- ReplyQueue::iterator it = impl.mReplyQueue.begin();
- ReplyQueue::iterator end = impl.mReplyQueue.end();
-
- for(; it != end; ++it)
- {
- const PendingReply& reply = (*it);
-
- if ((callback == reply.mCallback)
- && (id == reply.mID)
- && (user_data == reply.mData) )
- {
- impl.mReplyQueue.erase(it);
- return;
- }
- }
+ impl.mUpstreamHost = upstream_host;
}
-void LLCacheName::importFile(FILE* fp)
+boost::signals2::connection LLCacheName::addObserver(const LLCacheNameCallback& callback)
{
- S32 count = 0;
-
- const S32 BUFFER_SIZE = 1024;
- char buffer[BUFFER_SIZE]; /*Flawfinder: ignore*/
-
- // *NOTE: These buffer sizes are hardcoded into sscanf() below
- char id_string[MAX_STRING]; /*Flawfinder: ignore*/
- char firstname[MAX_STRING]; /*Flawfinder: ignore*/
- char lastname[MAX_STRING]; /*Flawfinder: ignore*/
- U32 create_time;
-
- // This is OK if the first line is actually a name. We just don't load it.
- char* valid = fgets(buffer, BUFFER_SIZE, fp);
- if (!valid) return;
-
- // *NOTE: This buffer size is hardcoded into sscanf() below
- char version_string[BUFFER_SIZE]; /*Flawfinder: ignore*/
- S32 version = 0;
- S32 match = sscanf( /* Flawfinder: ignore */
- buffer,
- "%1023s %d",
- version_string, &version);
- if ( match != 2
- || strcmp(version_string, "version")
- || version != CN_FILE_VERSION)
- {
- llwarns << "Ignoring old cache name file format" << llendl;
- return;
- }
-
- // We'll expire entries more than a week old
- U32 now = (U32)time(NULL);
- const U32 SECS_PER_DAY = 60 * 60 * 24;
- U32 delete_before_time = now - (7 * SECS_PER_DAY);
-
- while(!feof(fp))
- {
- valid = fgets(buffer, BUFFER_SIZE, fp);
- if (!valid) break;
-
- match = sscanf( /* Flawfinder: ignore */
- buffer,
- "%254s %u %254s %254s",
- id_string,
- &create_time,
- firstname,
- lastname);
- if (4 != match) continue;
-
- LLUUID id(id_string);
- if (id.isNull()) continue;
-
- // undo trivial XOR
- S32 i;
- for (i = 0; i < UUID_BYTES; i++)
- {
- id.mData[i] ^= 0x33;
- }
-
- // Don't load entries that are more than a week old
- if (create_time < delete_before_time) continue;
-
- LLCacheNameEntry* entry = new LLCacheNameEntry();
- entry->mIsGroup = false;
- entry->mCreateTime = create_time;
- LLString::copy(entry->mFirstName, firstname, DB_FIRST_NAME_BUF_SIZE);
- LLString::copy(entry->mLastName, lastname, DB_LAST_NAME_BUF_SIZE);
- impl.mCache[id] = entry;
-
- count++;
- }
-
- llinfos << "LLCacheName loaded " << count << " names" << llendl;
+ return impl.mSignal.connect(callback);
}
bool LLCacheName::importFile(std::istream& istr)
{
LLSD data;
- if(LLSDSerialize::fromXML(data, istr) < 1)
+ if(LLSDSerialize::fromXMLDocument(data, istr) < 1)
return false;
// We'll expire entries more than a week old
@@ -425,13 +330,12 @@ bool LLCacheName::importFile(std::istream& istr)
LLCacheNameEntry* entry = new LLCacheNameEntry();
entry->mIsGroup = false;
entry->mCreateTime = ctime;
- std::string first = agent[FIRST].asString();
- first.copy(entry->mFirstName, DB_FIRST_NAME_BUF_SIZE, 0);
- entry->mFirstName[llmin(first.size(),(std::string::size_type)DB_FIRST_NAME_BUF_SIZE-1)] = '\0';
- std::string last = agent[LAST].asString();
- last.copy(entry->mLastName, DB_LAST_NAME_BUF_SIZE, 0);
- entry->mLastName[llmin(last.size(),(std::string::size_type)DB_LAST_NAME_BUF_SIZE-1)] = '\0';
+ entry->mFirstName = agent[FIRST].asString();
+ entry->mLastName = agent[LAST].asString();
impl.mCache[id] = entry;
+ std::string fullname = buildFullName(entry->mFirstName, entry->mLastName);
+ impl.mReverseCache[fullname] = id;
+
++count;
}
llinfos << "LLCacheName loaded " << count << " agent names" << llendl;
@@ -450,10 +354,9 @@ bool LLCacheName::importFile(std::istream& istr)
LLCacheNameEntry* entry = new LLCacheNameEntry();
entry->mIsGroup = true;
entry->mCreateTime = ctime;
- std::string name = group[NAME].asString();
- name.copy(entry->mGroupName, DB_GROUP_NAME_BUF_SIZE, 0);
- entry->mGroupName[llmin(name.size(), (std::string::size_type)DB_GROUP_NAME_BUF_SIZE-1)] = '\0';
+ entry->mGroupName = group[NAME].asString();
impl.mCache[id] = entry;
+ impl.mReverseCache[entry->mGroupName] = id;
++count;
}
llinfos << "LLCacheName loaded " << count << " group names" << llendl;
@@ -470,8 +373,8 @@ void LLCacheName::exportFile(std::ostream& ostr)
// Only write entries for which we have valid data.
LLCacheNameEntry* entry = iter->second;
if(!entry
- || (NULL != strchr(entry->mFirstName, '?'))
- || (NULL != strchr(entry->mGroupName, '?')))
+ || (std::string::npos != entry->mFirstName.find('?'))
+ || (std::string::npos != entry->mGroupName.find('?')))
{
continue;
}
@@ -479,13 +382,14 @@ void LLCacheName::exportFile(std::ostream& ostr)
// store it
LLUUID id = iter->first;
std::string id_str = id.asString();
- if(entry->mFirstName[0] && entry->mLastName[0])
+ // IDEVO TODO: Should we store SLIDs with last name "Resident" or not?
+ if(!entry->mFirstName.empty() && !entry->mLastName.empty())
{
data[AGENTS][id_str][FIRST] = entry->mFirstName;
data[AGENTS][id_str][LAST] = entry->mLastName;
data[AGENTS][id_str][CTIME] = (S32)entry->mCreateTime;
}
- else if(entry->mIsGroup && entry->mGroupName[0])
+ else if(entry->mIsGroup && !entry->mGroupName.empty())
{
data[GROUPS][id_str][NAME] = entry->mGroupName;
data[GROUPS][id_str][CTIME] = (S32)entry->mCreateTime;
@@ -496,16 +400,16 @@ void LLCacheName::exportFile(std::ostream& ostr)
}
-BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& last)
+BOOL LLCacheName::Impl::getName(const LLUUID& id, std::string& first, std::string& last)
{
if(id.isNull())
{
- first = CN_NOBODY;
+ first = sCacheName["nobody"];
last.clear();
- return FALSE;
+ return TRUE;
}
- LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id );
+ LLCacheNameEntry* entry = get_ptr_in_map(mCache, id );
if (entry)
{
first = entry->mFirstName;
@@ -514,45 +418,46 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las
}
else
{
- first = CN_WAITING;
+ first = sCacheName["waiting"];
last.clear();
- if (!impl.isRequestPending(id))
+ if (!isRequestPending(id))
{
- impl.mAskNameQueue.insert(id);
+ mAskNameQueue.insert(id);
}
return FALSE;
}
}
-BOOL LLCacheName::getFullName(const LLUUID& id, std::string& fullname)
+// static
+void LLCacheName::localizeCacheName(std::string key, std::string value)
{
- std::string first_name, last_name;
- BOOL res = getName(id, first_name, last_name);
- fullname = first_name + " " + last_name;
- return res;
+ if (key!="" && value!= "" )
+ sCacheName[key]=value;
+ else
+ llwarns<< " Error localizing cache key " << key << " To "<< value<<llendl;
}
-// *TODO: Deprecate
-BOOL LLCacheName::getName(const LLUUID& id, char* first, char* last)
+BOOL LLCacheName::getFullName(const LLUUID& id, std::string& fullname)
{
std::string first_name, last_name;
- BOOL res = getName(id, first_name, last_name);
- strcpy(first, first_name.c_str());
- strcpy(last, last_name.c_str());
+ BOOL res = impl.getName(id, first_name, last_name);
+ fullname = buildFullName(first_name, last_name);
return res;
}
+
+
BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
{
if(id.isNull())
{
- group = CN_NONE;
- return FALSE;
+ group = sCacheName["none"];
+ return TRUE;
}
LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache,id);
- if (entry && !entry->mGroupName[0])
+ if (entry && entry->mGroupName.empty())
{
// COUNTER-HACK to combat James' HACK in exportFile()...
// this group name was loaded from a name cache that did not
@@ -568,7 +473,7 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
}
else
{
- group = CN_WAITING;
+ group = sCacheName["waiting"];
if (!impl.isRequestPending(id))
{
impl.mAskGroupQueue.insert(id);
@@ -577,36 +482,109 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
}
}
-// *TODO: Deprecate
-BOOL LLCacheName::getGroupName(const LLUUID& id, char* group)
+BOOL LLCacheName::getUUID(const std::string& first, const std::string& last, LLUUID& id)
{
- std::string group_name;
- BOOL res = getGroupName(id, group_name);
- strcpy(group, group_name.c_str());
- return res;
+ std::string full_name = buildFullName(first, last);
+ return getUUID(full_name, id);
+}
+
+BOOL LLCacheName::getUUID(const std::string& full_name, LLUUID& id)
+{
+ ReverseCache::iterator iter = impl.mReverseCache.find(full_name);
+ if (iter != impl.mReverseCache.end())
+ {
+ id = iter->second;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+//static
+std::string LLCacheName::buildFullName(const std::string& first, const std::string& last)
+{
+ std::string fullname = first;
+ if (!last.empty()
+ && last != "Resident")
+ {
+ fullname += ' ';
+ fullname += last;
+ }
+ return fullname;
}
+//static
+std::string LLCacheName::cleanFullName(const std::string& full_name)
+{
+ return full_name.substr(0, full_name.find(" Resident"));
+}
-// TODO: Make the cache name callback take a SINGLE std::string,
-// not a separate first and last name.
-void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data)
+//static
+std::string LLCacheName::buildUsername(const std::string& full_name)
{
+ // rare, but handle hard-coded error names returned from server
+ if (full_name == "(\?\?\?) (\?\?\?)")
+ {
+ return "(\?\?\?)";
+ }
+
+ std::string::size_type index = full_name.find(' ');
+
+ if (index != std::string::npos)
+ {
+ std::string username;
+ username = full_name.substr(0, index);
+ std::string lastname = full_name.substr(index+1);
+
+ if (lastname != "Resident")
+ {
+ username = username + "." + lastname;
+ }
+
+ LLStringUtil::toLower(username);
+ return username;
+ }
+
+ // if the input wasn't a correctly formatted legacy name just return it unchanged
+ return full_name;
+}
+
+// This is a little bit kludgy. LLCacheNameCallback is a slot instead of a function pointer.
+// The reason it is a slot is so that the legacy get() function below can bind an old callback
+// and pass it as a slot. The reason it isn't a boost::function is so that trackable behavior
+// doesn't get lost. As a result, we have to bind the slot to a signal to call it, even when
+// we call it immediately. -Steve
+// NOTE: Even though passing first and last name is a bit of extra overhead, it eliminates the
+// potential need for any parsing should any code need to handle first and last name independently.
+boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback)
+{
+ boost::signals2::connection res;
+
if(id.isNull())
{
- callback(id, CN_NOBODY, "", is_group, user_data);
+ LLCacheNameSignal signal;
+ signal.connect(callback);
+ signal(id, sCacheName["nobody"], is_group);
+ return res;
}
LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id );
if (entry)
{
+ LLCacheNameSignal signal;
+ signal.connect(callback);
// id found in map therefore we can call the callback immediately.
if (entry->mIsGroup)
{
- callback(id, entry->mGroupName, "", entry->mIsGroup, user_data);
+ signal(id, entry->mGroupName, entry->mIsGroup);
}
else
{
- callback(id, entry->mFirstName, entry->mLastName, entry->mIsGroup, user_data);
+ std::string fullname =
+ buildFullName(entry->mFirstName, entry->mLastName);
+ signal(id, fullname, entry->mIsGroup);
}
}
else
@@ -623,12 +601,25 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb
impl.mAskNameQueue.insert(id);
}
}
- impl.mReplyQueue.push_back(PendingReply(id, callback, user_data));
+ res = impl.addPending(id, callback);
}
+ return res;
+}
+
+boost::signals2::connection LLCacheName::getGroup(const LLUUID& group_id,
+ const LLCacheNameCallback& callback)
+{
+ return get(group_id, true, callback);
+}
+
+boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, old_callback_t callback, void* user_data)
+{
+ return get(id, is_group, boost::bind(callback, _1, _2, _3, user_data));
}
void LLCacheName::processPending()
{
+ LLMemType mt_pp(LLMemType::MTYPE_CACHE_PROCESS_PENDING);
const F32 SECS_BETWEEN_PROCESS = 0.1f;
if(!impl.mProcessTimer.checkExpirationAndReset(SECS_BETWEEN_PROCESS))
{
@@ -695,7 +686,7 @@ void LLCacheName::dump()
{
llinfos
<< iter->first << " = "
- << entry->mFirstName << " " << entry->mLastName
+ << buildFullName(entry->mFirstName, entry->mLastName)
<< " @ " << entry->mCreateTime
<< llendl;
}
@@ -710,18 +701,31 @@ void LLCacheName::dumpStats()
<< " AskGroup=" << impl.mAskGroupQueue.size()
<< " Pending=" << impl.mPendingQueue.size()
<< " Reply=" << impl.mReplyQueue.size()
- << " Observers=" << impl.mObservers.size()
+// << " Observers=" << impl.mSignal.size()
<< llendl;
}
+void LLCacheName::clear()
+{
+ for_each(impl.mCache.begin(), impl.mCache.end(), DeletePairedPointer());
+ impl.mCache.clear();
+}
+
//static
-LLString LLCacheName::getDefaultName()
+std::string LLCacheName::getDefaultName()
{
- return LLString(CN_WAITING);
+ return sCacheName["waiting"];
+}
+
+//static
+std::string LLCacheName::getDefaultLastName()
+{
+ return "Resident";
}
void LLCacheName::Impl::processPendingAsks()
{
+ LLMemType mt_ppa(LLMemType::MTYPE_CACHE_PROCESS_PENDING_ASKS);
sendRequest(_PREHASH_UUIDNameRequest, mAskNameQueue);
sendRequest(_PREHASH_UUIDGroupNameRequest, mAskGroupQueue);
mAskNameQueue.clear();
@@ -730,50 +734,52 @@ void LLCacheName::Impl::processPendingAsks()
void LLCacheName::Impl::processPendingReplies()
{
- ReplyQueue::iterator it = mReplyQueue.begin();
- ReplyQueue::iterator end = mReplyQueue.end();
-
+ LLMemType mt_ppr(LLMemType::MTYPE_CACHE_PROCESS_PENDING_REPLIES);
// First call all the callbacks, because they might send messages.
- for(; it != end; ++it)
+ for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); ++it)
{
- LLCacheNameEntry* entry = get_ptr_in_map(mCache, it->mID);
+ PendingReply* reply = *it;
+ LLCacheNameEntry* entry = get_ptr_in_map(mCache, reply->mID);
if(!entry) continue;
- if (it->mCallback)
+ if (!entry->mIsGroup)
{
- if (!entry->mIsGroup)
- {
- (it->mCallback)(it->mID,
- entry->mFirstName, entry->mLastName,
- FALSE, it->mData);
- }
- else {
- (it->mCallback)(it->mID,
- entry->mGroupName, "",
- TRUE, it->mData);
- }
+ std::string fullname =
+ LLCacheName::buildFullName(entry->mFirstName, entry->mLastName);
+ (reply->mSignal)(reply->mID, fullname, false);
+ }
+ else
+ {
+ (reply->mSignal)(reply->mID, entry->mGroupName, true);
}
}
// Forward on all replies, if needed.
ReplySender sender(mMsg);
- for (it = mReplyQueue.begin(); it != end; ++it)
+ for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); ++it)
{
- LLCacheNameEntry* entry = get_ptr_in_map(mCache, it->mID);
+ PendingReply* reply = *it;
+ LLCacheNameEntry* entry = get_ptr_in_map(mCache, reply->mID);
if(!entry) continue;
- if (it->mHost.isOk())
+ if (reply->mHost.isOk())
{
- sender.send(it->mID, *entry, it->mHost);
+ sender.send(reply->mID, *entry, reply->mHost);
}
- it->done();
+ reply->done();
+ }
+
+ for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); )
+ {
+ ReplyQueue::iterator curit = it++;
+ PendingReply* reply = *curit;
+ if (reply->isDone())
+ {
+ delete reply;
+ mReplyQueue.erase(curit);
+ }
}
-
- mReplyQueue.erase(
- remove_if(mReplyQueue.begin(), mReplyQueue.end(),
- std::mem_fun_ref(&PendingReply::isDone)),
- mReplyQueue.end());
}
@@ -811,18 +817,6 @@ void LLCacheName::Impl::sendRequest(
}
}
-void LLCacheName::Impl::notifyObservers(const LLUUID& id,
- const char* first, const char* last, BOOL is_group)
-{
- for (Observers::const_iterator i = mObservers.begin(),
- end = mObservers.end();
- i != end;
- ++i)
- {
- (**i)(id, first, last, is_group, NULL);
- }
-}
-
bool LLCacheName::Impl::isRequestPending(const LLUUID& id)
{
U32 now = (U32)time(NULL);
@@ -889,7 +883,7 @@ void LLCacheName::Impl::processUUIDRequest(LLMessageSystem* msg, bool isGroup)
}
}
- mReplyQueue.push_back(PendingReply(id, fromHost));
+ addPending(id, fromHost);
}
}
}
@@ -916,23 +910,39 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup)
entry->mCreateTime = (U32)time(NULL);
if (!isGroup)
{
- msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_FirstName, DB_FIRST_NAME_BUF_SIZE, entry->mFirstName, i);
- msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_LastName, DB_LAST_NAME_BUF_SIZE, entry->mLastName, i);
+ msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_FirstName, entry->mFirstName, i);
+ msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_LastName, entry->mLastName, i);
}
else
- {
- msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_GroupName, DB_GROUP_NAME_BUF_SIZE, entry->mGroupName, i);
+ { // is group
+ msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_GroupName, entry->mGroupName, i);
+ LLStringFn::replace_ascii_controlchars(entry->mGroupName, LL_UNKNOWN_CHAR);
}
if (!isGroup)
{
- notifyObservers(id,
- entry->mFirstName, entry->mLastName,
- FALSE);
+ // NOTE: Very occasionally the server sends down a full name
+ // in the first name field with an empty last name, for example,
+ // first = "Ladanie1 Resident", last = "".
+ // I cannot reproduce this, nor can I find a bug in the server code.
+ // Ensure "Resident" does not appear via cleanFullName, because
+ // buildFullName only checks last name. JC
+ std::string full_name;
+ if (entry->mLastName.empty())
+ {
+ full_name = cleanFullName(entry->mFirstName);
+ }
+ else
+ {
+ full_name = LLCacheName::buildFullName(entry->mFirstName, entry->mLastName);
+ }
+ mSignal(id, full_name, false);
+ mReverseCache[full_name] = id;
}
else
{
- notifyObservers(id, entry->mGroupName, "", TRUE);
+ mSignal(id, entry->mGroupName, true);
+ mReverseCache[entry->mGroupName] = id;
}
}
}
@@ -960,4 +970,3 @@ void LLCacheName::Impl::handleUUIDGroupNameReply(LLMessageSystem* msg, void** us
{
((LLCacheName::Impl*)userData)->processUUIDReply(msg, true);
}
-