summaryrefslogtreecommitdiff
path: root/indra/llmessage
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage')
-rw-r--r--indra/llmessage/CMakeLists.txt2
-rw-r--r--indra/llmessage/llavatarnamecache.cpp315
-rw-r--r--indra/llmessage/llavatarnamecache.h74
-rw-r--r--indra/llmessage/llcachename.cpp191
-rw-r--r--indra/llmessage/llcachename.h39
-rw-r--r--indra/llmessage/mean_collision_data.h5
6 files changed, 500 insertions, 126 deletions
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 1f8ee26716..0d07015f24 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -25,6 +25,7 @@ set(llmessage_SOURCE_FILES
llares.cpp
llareslistener.cpp
llassetstorage.cpp
+ llavatarnamecache.cpp
llblowfishcipher.cpp
llbuffer.cpp
llbufferstream.cpp
@@ -110,6 +111,7 @@ set(llmessage_HEADER_FILES
llares.h
llareslistener.h
llassetstorage.h
+ llavatarnamecache.h
llblowfishcipher.h
llbuffer.h
llbufferstream.h
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
new file mode 100644
index 0000000000..5384e1f067
--- /dev/null
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -0,0 +1,315 @@
+/**
+ * @file llavatarnamecache.cpp
+ * @brief Provides lookup of avatar SLIDs ("bobsmith123") and display names
+ * ("James Cook") from avatar UUIDs.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * 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://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * 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://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * 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.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "llavatarnamecache.h"
+
+#include "llcachename.h" // *TODO: remove
+#include "llframetimer.h"
+#include "llhttpclient.h"
+
+#include <map>
+#include <set>
+
+namespace LLAvatarNameCache
+{
+ bool sUseDisplayNames = false;
+
+ // *TODO: configure the base URL for this in viewer with data
+ // from login.cgi
+ std::string sNameServiceBaseURL = "http://pdp15.lindenlab.com:8050/my-service/";
+
+ // accumulated agent IDs for next query against service
+ typedef std::set<LLUUID> ask_queue_t;
+ ask_queue_t sAskQueue;
+
+ // agent IDs that have been requested, but with no reply
+ // maps agent ID to frame time request was made
+ typedef std::map<LLUUID, F32> pending_queue_t;
+ pending_queue_t sPendingQueue;
+
+ // Callbacks to fire when we received a name.
+ // May have multiple callbacks for a single ID, which are
+ // represented as multiple slots bound to the signal.
+ // Avoid copying signals via pointers.
+ typedef std::map<LLUUID, callback_signal_t*> signal_map_t;
+ signal_map_t sSignalMap;
+
+ // names we know about
+ typedef std::map<LLUUID, LLAvatarName> cache_t;
+ cache_t sCache;
+
+ // only need per-frame timing resolution
+ LLFrameTimer sRequestTimer;
+
+ bool isRequestPending(const LLUUID& agent_id);
+ void processNameFromService(const LLSD& row);
+}
+
+class LLAvatarNameResponder : public LLHTTPClient::Responder
+{
+public:
+ /*virtual*/ void result(const LLSD& content)
+ {
+ LLSD::array_const_iterator it = content.beginArray();
+ for ( ; it != content.endArray(); ++it)
+ {
+ const LLSD& row = *it;
+ LLAvatarNameCache::processNameFromService(row);
+ }
+ }
+
+ /*virtual*/ void error(U32 status, const std::string& reason)
+ {
+ llinfos << "JAMESDEBUG error " << status << " " << reason << llendl;
+ }
+};
+
+void LLAvatarNameCache::processNameFromService(const LLSD& row)
+{
+ U32 now = (U32)LLFrameTimer::getTotalSeconds();
+
+ LLAvatarName av_name;
+ av_name.mSLID = row["slid"].asString();
+ av_name.mDisplayName = row["display_name"].asString();
+ av_name.mLastUpdate = now;
+
+ // HACK for pretty stars
+ if (row["last_name"].asString() == "Linden")
+ {
+ av_name.mBadge = "Person_Star";
+ }
+
+ // Some avatars don't have explicit display names set
+ if (av_name.mDisplayName.empty())
+ {
+ // make up a display name
+ std::string first_name = row["first_name"].asString();
+ std::string last_name = row["last_name"].asString();
+ av_name.mDisplayName =
+ LLCacheName::buildFullName(first_name, last_name);
+ av_name.mIsLegacy = true;
+ }
+
+ // add to cache
+ LLUUID agent_id = row["agent_id"].asUUID();
+ sCache[agent_id] = av_name;
+
+ sPendingQueue.erase(agent_id);
+
+ // signal everyone waiting on this name
+ signal_map_t::iterator sig_it = sSignalMap.find(agent_id);
+ if (sig_it != sSignalMap.end())
+ {
+ callback_signal_t* signal = sig_it->second;
+ (*signal)(agent_id, av_name);
+
+ sSignalMap.erase(agent_id);
+
+ delete signal;
+ signal = NULL;
+ }
+}
+
+void LLAvatarNameCache::initClass()
+{
+}
+
+void LLAvatarNameCache::cleanupClass()
+{
+}
+
+void LLAvatarNameCache::importFile(std::istream& istr)
+{
+}
+
+void LLAvatarNameCache::exportFile(std::ostream& ostr)
+{
+}
+
+void LLAvatarNameCache::idle()
+{
+ const F32 SECS_BETWEEN_REQUESTS = 0.2f; // JAMESDEBUG set to 0.1?
+ if (sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS))
+ {
+ return;
+ }
+
+ if (sAskQueue.empty())
+ {
+ return;
+ }
+
+ LLSD body;
+ body["agent_ids"] = LLSD::emptyArray();
+ LLSD& agent_ids = body["agent_ids"];
+
+ ask_queue_t::const_iterator it = sAskQueue.begin();
+ for ( ; it != sAskQueue.end(); ++it)
+ {
+ agent_ids.append( LLSD( *it ) );
+ }
+
+ // *TODO: configure the base URL for this
+ std::string url = sNameServiceBaseURL + "agent/display-names/";
+ LLHTTPClient::post(url, body, new LLAvatarNameResponder());
+
+ // Move requests from Ask queue to Pending queue
+ U32 now = (U32)LLFrameTimer::getTotalSeconds();
+ for (it = sAskQueue.begin(); it != sAskQueue.end(); ++it)
+ {
+ sPendingQueue[*it] = now;
+ }
+ sAskQueue.clear();
+}
+
+bool LLAvatarNameCache::isRequestPending(const LLUUID& agent_id)
+{
+ const U32 PENDING_TIMEOUT_SECS = 5 * 60;
+ U32 now = (U32)LLFrameTimer::getTotalSeconds();
+ U32 expire_time = now - PENDING_TIMEOUT_SECS;
+
+ pending_queue_t::const_iterator it = sPendingQueue.find(agent_id);
+ if (it != sPendingQueue.end())
+ {
+ bool expired = (it->second < expire_time);
+ return !expired;
+ }
+ return false;
+}
+
+bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
+{
+ std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id);
+ if (it != sCache.end())
+ {
+ *av_name = it->second;
+ return true;
+ }
+
+ if (!isRequestPending(agent_id))
+ {
+ sAskQueue.insert(agent_id);
+ }
+
+ return false;
+}
+
+void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot)
+{
+ std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id);
+ if (it != sCache.end())
+ {
+ // ...name already exists in cache, fire callback now
+ callback_signal_t signal;
+ signal.connect(slot);
+ signal(agent_id, it->second);
+ return;
+ }
+
+ // schedule a request
+ if (!isRequestPending(agent_id))
+ {
+ sAskQueue.insert(agent_id);
+ }
+
+ // always store additional callback, even if request is pending
+ signal_map_t::iterator sig_it = sSignalMap.find(agent_id);
+ if (sig_it == sSignalMap.end())
+ {
+ // ...new callback for this id
+ callback_signal_t* signal = new callback_signal_t();
+ signal->connect(slot);
+ sSignalMap[agent_id] = signal;
+ }
+ else
+ {
+ // ...existing callback, bind additional slot
+ callback_signal_t* signal = sig_it->second;
+ signal->connect(slot);
+ }
+}
+
+class LLSetNameResponder : public LLHTTPClient::Responder
+{
+public:
+ LLUUID mAgentID;
+
+ LLSetNameResponder(const LLUUID& agent_id) : mAgentID(agent_id) { }
+
+ /*virtual*/ void result(const LLSD& content)
+ {
+ // force re-fetch
+ LLAvatarNameCache::sCache.erase(mAgentID);
+ }
+
+ /*virtual*/ void error(U32 status, const std::string& reason)
+ {
+ llinfos << "JAMESDEBUG set names failed " << status
+ << " reason " << reason << llendl;
+ }
+};
+
+void LLAvatarNameCache::setDisplayName(const LLUUID& agent_id, const std::string& display_name)
+{
+ LLSD body;
+ body["display_name"] = display_name;
+
+ // *TODO: configure the base URL for this
+ std::string url = sNameServiceBaseURL + "agent/";
+ url += agent_id.asString();
+ url += "/set-display-name/";
+ LLHTTPClient::post(url, body, new LLSetNameResponder(agent_id));
+}
+
+void LLAvatarNameCache::toggleDisplayNames()
+{
+ sUseDisplayNames = !sUseDisplayNames;
+ // flush our cache
+ sCache.clear();
+ // force re-lookups
+ if (gCacheName)
+ {
+ gCacheName->clear();
+ }
+}
+
+bool LLAvatarNameCache::useDisplayNames()
+{
+ return sUseDisplayNames;
+}
+
+void LLAvatarNameCache::erase(const LLUUID& agent_id)
+{
+ sCache.erase(agent_id);
+}
diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h
new file mode 100644
index 0000000000..a09f549877
--- /dev/null
+++ b/indra/llmessage/llavatarnamecache.h
@@ -0,0 +1,74 @@
+/**
+ * @file llavatarnamecache.h
+ * @brief Provides lookup of avatar SLIDs ("bobsmith123") and display names
+ * ("James Cook") from avatar UUIDs.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * 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://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * 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://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * 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.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLAVATARNAMECACHE_H
+#define LLAVATARNAMECACHE_H
+
+#include "llavatarname.h" // for convenience
+
+#include <boost/signals2.hpp>
+
+namespace LLAvatarNameCache
+{
+ void initClass();
+ void cleanupClass();
+
+ void importFile(std::istream& istr);
+ void exportFile(std::ostream& ostr);
+
+ // Periodically makes a batch request for display names not already in
+ // cache. Call once per frame.
+ void idle();
+
+ // If name is in cache, returns true and fills in provided LLAvatarName
+ // otherwise returns false
+ bool get(const LLUUID& agent_id, LLAvatarName *av_name);
+
+ typedef boost::signals2::signal<
+ void (const LLUUID& agent_id, const LLAvatarName& av_name)>
+ callback_signal_t;
+ typedef callback_signal_t::slot_type callback_slot_t;
+
+ // Fetches name information and calls callback.
+ // If name information is in cache, callback will be called immediately.
+ void get(const LLUUID& agent_id, callback_slot_t slot);
+
+ // Sends an update to the server
+ void setDisplayName(const LLUUID& agent_id, const std::string& display_name);
+
+ // HACK: turn display names on and off
+ void toggleDisplayNames();
+ bool useDisplayNames();
+ void erase(const LLUUID& agent_id);
+}
+
+#endif
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index 9363b3a8d5..d7d49eac8d 100644
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -75,6 +75,8 @@ public:
public:
bool mIsGroup;
U32 mCreateTime; // unix time_t
+ // IDEVO TODO collapse names to one field, which will eliminate
+ // many string compares on "Resident"
std::string mFirstName;
std::string mLastName;
std::string mGroupName;
@@ -220,7 +222,9 @@ public:
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);
@@ -306,89 +310,10 @@ boost::signals2::connection LLCacheName::addObserver(const LLCacheNameCallback&
return impl.mSignal.connect(callback);
}
-void LLCacheName::importFile(LLFILE* fp)
-{
- 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;
- entry->mFirstName = firstname;
- entry->mLastName = lastname;
- impl.mCache[id] = entry;
- std::string fullname = entry->mFirstName + " " + entry->mLastName;
- impl.mReverseCache[fullname] = id;
-
- count++;
- }
-
- llinfos << "LLCacheName loaded " << count << " names" << llendl;
-}
-
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
@@ -414,7 +339,7 @@ bool LLCacheName::importFile(std::istream& istr)
entry->mFirstName = agent[FIRST].asString();
entry->mLastName = agent[LAST].asString();
impl.mCache[id] = entry;
- std::string fullname = entry->mFirstName + " " + entry->mLastName;
+ std::string fullname = buildFullName(entry->mFirstName, entry->mLastName);
impl.mReverseCache[fullname] = id;
++count;
@@ -463,6 +388,7 @@ void LLCacheName::exportFile(std::ostream& ostr)
// store it
LLUUID id = iter->first;
std::string id_str = id.asString();
+ // 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;
@@ -480,7 +406,7 @@ 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())
{
@@ -489,7 +415,7 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las
return FALSE;
}
- LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id );
+ LLCacheNameEntry* entry = get_ptr_in_map(mCache, id );
if (entry)
{
first = entry->mFirstName;
@@ -500,16 +426,17 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las
{
first = sCacheName["waiting"];
last.clear();
- if (!impl.isRequestPending(id))
+ if (!isRequestPending(id))
{
- impl.mAskNameQueue.insert(id);
+ mAskNameQueue.insert(id);
}
return FALSE;
}
}
+
// static
-void LLCacheName::LocalizeCacheName(std::string key, std::string value)
+void LLCacheName::localizeCacheName(std::string key, std::string value)
{
if (key!="" && value!= "" )
sCacheName[key]=value;
@@ -520,11 +447,13 @@ void LLCacheName::LocalizeCacheName(std::string key, std::string value)
BOOL LLCacheName::getFullName(const LLUUID& id, std::string& fullname)
{
std::string first_name, last_name;
- BOOL res = getName(id, first_name, last_name);
- fullname = first_name + " " + last_name;
+ 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())
@@ -561,13 +490,13 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
BOOL LLCacheName::getUUID(const std::string& first, const std::string& last, LLUUID& id)
{
- std::string fullname = first + " " + last;
- return getUUID(fullname, id);
+ std::string full_name = buildFullName(first, last);
+ return getUUID(full_name, id);
}
-BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id)
+BOOL LLCacheName::getUUID(const std::string& full_name, LLUUID& id)
{
- ReverseCache::iterator iter = impl.mReverseCache.find(fullname);
+ ReverseCache::iterator iter = impl.mReverseCache.find(full_name);
if (iter != impl.mReverseCache.end())
{
id = iter->second;
@@ -579,6 +508,25 @@ BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id)
}
}
+//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"));
+}
+
// 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
@@ -586,7 +534,7 @@ BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id)
// 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 LLCacheName::get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback)
{
boost::signals2::connection res;
@@ -594,7 +542,7 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co
{
LLCacheNameSignal signal;
signal.connect(callback);
- signal(id, sCacheName["nobody"], "", is_group);
+ signal(id, sCacheName["nobody"], is_group);
return res;
}
@@ -606,11 +554,13 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co
// id found in map therefore we can call the callback immediately.
if (entry->mIsGroup)
{
- signal(id, entry->mGroupName, "", entry->mIsGroup);
+ signal(id, entry->mGroupName, entry->mIsGroup);
}
else
{
- signal(id, entry->mFirstName, entry->mLastName, entry->mIsGroup);
+ std::string fullname =
+ buildFullName(entry->mFirstName, entry->mLastName);
+ signal(id, fullname, entry->mIsGroup);
}
}
else
@@ -632,9 +582,9 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co
return res;
}
-boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data)
+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, _4, user_data));
+ return get(id, is_group, boost::bind(callback, _1, _2, _3, user_data));
}
void LLCacheName::processPending()
@@ -706,7 +656,7 @@ void LLCacheName::dump()
{
llinfos
<< iter->first << " = "
- << entry->mFirstName << " " << entry->mLastName
+ << buildFullName(entry->mFirstName, entry->mLastName)
<< " @ " << entry->mCreateTime
<< llendl;
}
@@ -725,12 +675,24 @@ void LLCacheName::dumpStats()
<< llendl;
}
+void LLCacheName::clear()
+{
+ for_each(impl.mCache.begin(), impl.mCache.end(), DeletePairedPointer());
+ impl.mCache.clear();
+}
+
//static
std::string LLCacheName::getDefaultName()
{
return sCacheName["waiting"];
}
+//static
+std::string LLCacheName::getDefaultLastName()
+{
+ return "Resident";
+}
+
void LLCacheName::Impl::processPendingAsks()
{
LLMemType mt_ppa(LLMemType::MTYPE_CACHE_PROCESS_PENDING_ASKS);
@@ -752,11 +714,13 @@ void LLCacheName::Impl::processPendingReplies()
if (!entry->mIsGroup)
{
- (reply->mSignal)(reply->mID, entry->mFirstName, entry->mLastName, FALSE);
+ std::string fullname =
+ LLCacheName::buildFullName(entry->mFirstName, entry->mLastName);
+ (reply->mSignal)(reply->mID, fullname, false);
}
else
{
- (reply->mSignal)(reply->mID, entry->mGroupName, "", TRUE);
+ (reply->mSignal)(reply->mID, entry->mGroupName, true);
}
}
@@ -927,13 +891,27 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup)
if (!isGroup)
{
- mSignal(id, entry->mFirstName, entry->mLastName, FALSE);
- std::string fullname = entry->mFirstName + " " + entry->mLastName;
- mReverseCache[fullname] = id;
+ // 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
{
- mSignal(id, entry->mGroupName, "", TRUE);
+ mSignal(id, entry->mGroupName, true);
mReverseCache[entry->mGroupName] = id;
}
}
@@ -962,4 +940,3 @@ void LLCacheName::Impl::handleUUIDGroupNameReply(LLMessageSystem* msg, void** us
{
((LLCacheName::Impl*)userData)->processUUIDReply(msg, true);
}
-
diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h
index 111cc8b650..6b6bbde6ab 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -42,13 +42,12 @@ class LLUUID;
typedef boost::signals2::signal<void (const LLUUID& id,
- const std::string& first_name,
- const std::string& last_name,
- BOOL is_group)> LLCacheNameSignal;
+ const std::string& name,
+ bool is_group)> LLCacheNameSignal;
typedef LLCacheNameSignal::slot_type LLCacheNameCallback;
// Old callback with user data for compatability
-typedef void (*old_callback_t)(const LLUUID&, const std::string&, const std::string&, BOOL, void*);
+typedef void (*old_callback_t)(const LLUUID&, const std::string&, bool, void*);
// Here's the theory:
// If you request a name that isn't in the cache, it returns "waiting"
@@ -71,24 +70,26 @@ public:
boost::signals2::connection addObserver(const LLCacheNameCallback& callback);
- // janky old format. Remove after a while. Phoenix. 2008-01-30
- void importFile(LLFILE* fp);
-
// storing cache on disk; for viewer, in name.cache
bool importFile(std::istream& istr);
void exportFile(std::ostream& ostr);
- // If available, copies the first and last name into the strings provided.
- // first must be at least DB_FIRST_NAME_BUF_SIZE characters.
- // last must be at least DB_LAST_NAME_BUF_SIZE characters.
+ // If available, copies name ("bobsmith123" or "James Linden") into string
// If not available, copies the string "waiting".
// Returns TRUE iff available.
- BOOL getName(const LLUUID& id, std::string& first, std::string& last);
- BOOL getFullName(const LLUUID& id, std::string& fullname);
-
+ BOOL getFullName(const LLUUID& id, std::string& full_name);
+
// Reverse lookup of UUID from name
BOOL getUUID(const std::string& first, const std::string& last, LLUUID& id);
BOOL getUUID(const std::string& fullname, LLUUID& id);
+
+ // IDEVO Temporary code
+ // Clean up new-style "bobsmith123 Resident" names to "bobsmith123" for display
+ static std::string buildFullName(const std::string& first, const std::string& last);
+
+ // Clean up legacy "bobsmith123 Resident" to "bobsmith123"
+ // If name does not contain "Resident" returns it unchanged.
+ static std::string cleanFullName(const std::string& full_name);
// If available, this method copies the group name into the string
// provided. The caller must allocate at least
@@ -100,10 +101,10 @@ public:
// If the data is currently available, may call the callback immediatly
// otherwise, will request the data, and will call the callback when
// available. There is no garuntee the callback will ever be called.
- boost::signals2::connection get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback);
+ boost::signals2::connection get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback);
// LEGACY
- boost::signals2::connection get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data);
+ boost::signals2::connection get(const LLUUID& id, bool is_group, old_callback_t callback, void* user_data);
// This method needs to be called from time to time to send out
// requests.
void processPending();
@@ -114,9 +115,15 @@ public:
// Debugging
void dump(); // Dumps the contents of the cache
void dumpStats(); // Dumps the sizes of the cache and associated queues.
+ void clear(); // Deletes all entries from the cache
static std::string getDefaultName();
- static void LocalizeCacheName(std::string key, std::string value);
+
+ // Returns "Resident", the default last name for SLID-based accounts
+ // that have no last name.
+ static std::string getDefaultLastName();
+
+ static void localizeCacheName(std::string key, std::string value);
static std::map<std::string, std::string> sCacheName;
private:
diff --git a/indra/llmessage/mean_collision_data.h b/indra/llmessage/mean_collision_data.h
index 03b96f9f90..a6c635e81e 100644
--- a/indra/llmessage/mean_collision_data.h
+++ b/indra/llmessage/mean_collision_data.h
@@ -61,7 +61,7 @@ public:
LLMeanCollisionData(LLMeanCollisionData *mcd)
: mVictim(mcd->mVictim), mPerp(mcd->mPerp), mTime(mcd->mTime), mType(mcd->mType), mMag(mcd->mMag),
- mFirstName(mcd->mFirstName), mLastName(mcd->mLastName)
+ mFullName(mcd->mFullName)
{
}
@@ -95,8 +95,7 @@ public:
time_t mTime;
EMeanCollisionType mType;
F32 mMag;
- std::string mFirstName;
- std::string mLastName;
+ std::string mFullName;
};