try save a few ns on chat to objects

master
UbitUmarov 2020-02-24 05:37:42 +00:00
parent df2536c407
commit 6cadcb8bdf
1 changed files with 107 additions and 101 deletions

View File

@ -97,7 +97,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
// private static readonly ILog m_log = // private static readonly ILog m_log =
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private const int DEBUG_CHANNEL = 2147483647; private const int DEBUG_CHANNEL = 0x7fffffff;
private ListenerManager m_listenerManager; private ListenerManager m_listenerManager;
private ConcurrentQueue<ListenerInfo> m_pending; private ConcurrentQueue<ListenerInfo> m_pending;
@ -131,6 +131,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
{ {
} }
m_whisperdistance *= m_whisperdistance;
m_saydistance *= m_saydistance;
m_shoutdistance *= m_shoutdistance;
if (maxlisteners < 1) if (maxlisteners < 1)
maxlisteners = int.MaxValue; maxlisteners = int.MaxValue;
if (maxhandles < 1) if (maxhandles < 1)
@ -314,42 +318,54 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
// m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}", // m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}",
// type, channel, name, id, msg); // type, channel, name, id, msg);
// validate type and set range
float maxDistanceSQ;
switch (type)
{
case ChatTypeEnum.Whisper:
maxDistanceSQ = m_whisperdistance;
break;
case ChatTypeEnum.Say:
maxDistanceSQ = m_saydistance;
break;
case ChatTypeEnum.Shout:
maxDistanceSQ = m_shoutdistance;
break;
case ChatTypeEnum.Region:
maxDistanceSQ = -1f;
break;
default:
return;
}
// Determine which listen event filters match the given set of arguments, this results // Determine which listen event filters match the given set of arguments, this results
// in a limited set of listeners, each belonging a host. If the host is in range, add them // in a limited set of listeners, each belonging a host. If the host is in range, add them
// to the pending queue. // to the pending queue.
UUID hostID;
foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
{ {
hostID = li.GetHostID();
// Dont process if this message is from yourself! // Dont process if this message is from yourself!
if (li.GetHostID().Equals(id)) if (id == hostID)
continue; continue;
SceneObjectPart sPart = m_scene.GetSceneObjectPart(li.GetHostID()); if(maxDistanceSQ < 0)
{
QueueMessage(new ListenerInfo(li, name, id, msg));
continue;
}
SceneObjectPart sPart = m_scene.GetSceneObjectPart(hostID);
if (sPart == null) if (sPart == null)
continue; continue;
double dis = Vector3.DistanceSquared(sPart.AbsolutePosition, position); if(maxDistanceSQ > Vector3.DistanceSquared(sPart.AbsolutePosition, position))
switch (type) QueueMessage(new ListenerInfo(li, name, id, msg));
{
case ChatTypeEnum.Whisper:
if (dis < m_whisperdistance * m_whisperdistance)
QueueMessage(new ListenerInfo(li, name, id, msg));
break;
case ChatTypeEnum.Say:
if (dis < m_saydistance * m_saydistance)
QueueMessage(new ListenerInfo(li, name, id, msg));
break;
case ChatTypeEnum.Shout:
if (dis < m_shoutdistance * m_shoutdistance)
QueueMessage(new ListenerInfo(li, name, id, msg));
break;
case ChatTypeEnum.Region:
QueueMessage(new ListenerInfo(li, name, id, msg));
break;
}
} }
} }
@ -506,8 +522,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
public class ListenerManager public class ListenerManager
{ {
private Dictionary<int, List<ListenerInfo>> m_listeners = private object mainLock = new object();
new Dictionary<int, List<ListenerInfo>>(); private Dictionary<int, List<ListenerInfo>> m_listenersByChannel = new Dictionary<int, List<ListenerInfo>>();
private int m_maxlisteners; private int m_maxlisteners;
private int m_maxhandles; private int m_maxhandles;
private int m_curlisteners; private int m_curlisteners;
@ -519,8 +535,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
{ {
get get
{ {
lock (m_listeners) lock (mainLock)
return m_listeners.Count; return m_listenersByChannel.Count;
} }
} }
@ -543,8 +559,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
int regexBitfield) int regexBitfield)
{ {
// do we already have a match on this particular filter event? // do we already have a match on this particular filter event?
List<ListenerInfo> coll = GetListeners(itemID, channel, name, id, List<ListenerInfo> coll = GetListeners(itemID, channel, name, id, msg);
msg);
if (coll.Count > 0) if (coll.Count > 0)
{ {
@ -553,7 +568,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
return coll[0].GetHandle(); return coll[0].GetHandle();
} }
lock (m_listeners) lock (mainLock)
{ {
if (m_curlisteners < m_maxlisteners) if (m_curlisteners < m_maxlisteners)
{ {
@ -565,12 +580,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
itemID, hostID, channel, name, id, msg, itemID, hostID, channel, name, id, msg,
regexBitfield); regexBitfield);
List<ListenerInfo> listeners; if (!m_listenersByChannel.TryGetValue(channel, out List<ListenerInfo> listeners))
if (!m_listeners.TryGetValue(
channel, out listeners))
{ {
listeners = new List<ListenerInfo>(); listeners = new List<ListenerInfo>();
m_listeners.Add(channel, listeners); m_listenersByChannel.Add(channel, listeners);
} }
listeners.Add(li); listeners.Add(li);
m_curlisteners++; m_curlisteners++;
@ -584,20 +597,18 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
public void Remove(UUID itemID, int handle) public void Remove(UUID itemID, int handle)
{ {
lock (m_listeners) lock (mainLock)
{ {
foreach (KeyValuePair<int, List<ListenerInfo>> lis foreach (KeyValuePair<int, List<ListenerInfo>> lis in m_listenersByChannel)
in m_listeners)
{ {
foreach (ListenerInfo li in lis.Value) foreach (ListenerInfo li in lis.Value)
{ {
if (li.GetItemID().Equals(itemID) && if (handle == li.GetHandle() && itemID == li.GetItemID())
li.GetHandle().Equals(handle))
{ {
lis.Value.Remove(li); lis.Value.Remove(li);
m_curlisteners--; m_curlisteners--;
if (lis.Value.Count == 0) if (lis.Value.Count == 0)
m_listeners.Remove(lis.Key); // bailing of loop so this does not smoke m_listenersByChannel.Remove(lis.Key); // bailing of loop so this does not smoke
// there should be only one, so we bail out early // there should be only one, so we bail out early
return; return;
} }
@ -611,53 +622,44 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
List<int> emptyChannels = new List<int>(); List<int> emptyChannels = new List<int>();
List<ListenerInfo> removedListeners = new List<ListenerInfo>(); List<ListenerInfo> removedListeners = new List<ListenerInfo>();
lock (m_listeners) lock (mainLock)
{ {
foreach (KeyValuePair<int, List<ListenerInfo>> lis foreach (KeyValuePair<int, List<ListenerInfo>> lis in m_listenersByChannel)
in m_listeners)
{ {
foreach (ListenerInfo li in lis.Value) foreach (ListenerInfo li in lis.Value)
{ {
if (li.GetItemID().Equals(itemID)) if (itemID == li.GetItemID())
{
// store them first, else the enumerated bails on
// us
removedListeners.Add(li); removedListeners.Add(li);
}
} }
foreach (ListenerInfo li in removedListeners) foreach (ListenerInfo li in removedListeners)
{ {
lis.Value.Remove(li); lis.Value.Remove(li);
m_curlisteners--; m_curlisteners--;
} }
removedListeners.Clear(); removedListeners.Clear();
if (lis.Value.Count == 0) if (lis.Value.Count == 0)
{
// again, store first, remove later
emptyChannels.Add(lis.Key); emptyChannels.Add(lis.Key);
}
} }
foreach (int channel in emptyChannels) foreach (int channel in emptyChannels)
{ {
m_listeners.Remove(channel); m_listenersByChannel.Remove(channel);
} }
} }
} }
public void Activate(UUID itemID, int handle) public void Activate(UUID itemID, int handle)
{ {
lock (m_listeners) lock (mainLock)
{ {
foreach (KeyValuePair<int, List<ListenerInfo>> lis foreach (KeyValuePair<int, List<ListenerInfo>> lis in m_listenersByChannel)
in m_listeners)
{ {
foreach (ListenerInfo li in lis.Value) foreach (ListenerInfo li in lis.Value)
{ {
if (li.GetItemID().Equals(itemID) && if (handle == li.GetHandle() && itemID == li.GetItemID())
li.GetHandle() == handle)
{ {
li.Activate(); li.Activate();
// only one, bail out
return; return;
} }
} }
@ -667,18 +669,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
public void Dectivate(UUID itemID, int handle) public void Dectivate(UUID itemID, int handle)
{ {
lock (m_listeners) lock (mainLock)
{ {
foreach (KeyValuePair<int, List<ListenerInfo>> lis foreach (KeyValuePair<int, List<ListenerInfo>> lis in m_listenersByChannel)
in m_listeners)
{ {
foreach (ListenerInfo li in lis.Value) foreach (ListenerInfo li in lis.Value)
{ {
if (li.GetItemID().Equals(itemID) && if (handle == li.GetHandle() && itemID == li.GetItemID())
li.GetHandle() == handle)
{ {
li.Deactivate(); li.Deactivate();
// only one, bail out
return; return;
} }
} }
@ -697,11 +696,11 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
List<int> handles = new List<int>(); List<int> handles = new List<int>();
// build a list of used keys for this specific itemID... // build a list of used keys for this specific itemID...
foreach (KeyValuePair<int, List<ListenerInfo>> lis in m_listeners) foreach (KeyValuePair<int, List<ListenerInfo>> lis in m_listenersByChannel)
{ {
foreach (ListenerInfo li in lis.Value) foreach (ListenerInfo li in lis.Value)
{ {
if (li.GetItemID().Equals(itemID)) if (itemID == li.GetItemID())
handles.Add(li.GetHandle()); handles.Add(li.GetHandle());
} }
} }
@ -741,8 +740,6 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
/// <remarks> /// <remarks>
/// Theres probably a more clever and efficient way to do this, maybe /// Theres probably a more clever and efficient way to do this, maybe
/// with regex. /// with regex.
/// PM2008: Ha, one could even be smart and define a specialized
/// Enumerator.
/// </remarks> /// </remarks>
/// <param name="itemID"></param> /// <param name="itemID"></param>
/// <param name="channel"></param> /// <param name="channel"></param>
@ -755,42 +752,52 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
{ {
List<ListenerInfo> collection = new List<ListenerInfo>(); List<ListenerInfo> collection = new List<ListenerInfo>();
lock (m_listeners) lock (mainLock)
{ {
List<ListenerInfo> listeners; List<ListenerInfo> listeners;
if (!m_listeners.TryGetValue(channel, out listeners)) if (!m_listenersByChannel.TryGetValue(channel, out listeners))
{ {
return collection; return collection;
} }
bool itemIDNotZero = itemID != UUID.Zero;
foreach (ListenerInfo li in listeners) foreach (ListenerInfo li in listeners)
{ {
if (!li.IsActive()) if (!li.IsActive())
{
continue; continue;
if (itemIDNotZero && itemID != li.GetItemID())
continue;
if (li.GetID() != UUID.Zero && id != li.GetID())
continue;
if (li.GetName().Length > 0)
{
if((li.RegexBitfield & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME)
{
if (!Regex.IsMatch(name, li.GetName()))
continue;
}
else
{
if (!li.GetName().Equals(name))
continue;
}
} }
if (!itemID.Equals(UUID.Zero) &&
!li.GetItemID().Equals(itemID)) if (li.GetMessage().Length > 0)
{ {
continue; if((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE)
} {
if (li.GetName().Length > 0 && ( if(!Regex.IsMatch(msg, li.GetMessage()))
((li.RegexBitfield & OS_LISTEN_REGEX_NAME) != OS_LISTEN_REGEX_NAME && !li.GetName().Equals(name)) || continue;
((li.RegexBitfield & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME && !Regex.IsMatch(name, li.GetName())) }
)) else
{ {
continue; if(!li.GetMessage().Equals(msg))
} continue;
if (!li.GetID().Equals(UUID.Zero) && !li.GetID().Equals(id)) }
{
continue;
}
if (li.GetMessage().Length > 0 && (
((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) != OS_LISTEN_REGEX_MESSAGE && !li.GetMessage().Equals(msg)) ||
((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE && !Regex.IsMatch(msg, li.GetMessage()))
))
{
continue;
} }
collection.Add(li); collection.Add(li);
} }
@ -802,9 +809,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
{ {
List<Object> data = new List<Object>(); List<Object> data = new List<Object>();
lock (m_listeners) lock (mainLock)
{ {
foreach (List<ListenerInfo> list in m_listeners.Values) foreach (List<ListenerInfo> list in m_listenersByChannel.Values)
{ {
foreach (ListenerInfo l in list) foreach (ListenerInfo l in list)
{ {
@ -832,14 +839,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
ListenerInfo info = ListenerInfo info =
ListenerInfo.FromData(localID, itemID, hostID, item); ListenerInfo.FromData(localID, itemID, hostID, item);
lock (m_listeners) lock (mainLock)
{ {
if (!m_listeners.ContainsKey((int)item[2])) if (!m_listenersByChannel.ContainsKey((int)item[2]))
{ {
m_listeners.Add((int)item[2], m_listenersByChannel.Add((int)item[2], new List<ListenerInfo>());
new List<ListenerInfo>());
} }
m_listeners[(int)item[2]].Add(info); m_listenersByChannel[(int)item[2]].Add(info);
} }
idx += dataItemLength; idx += dataItemLength;