aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/ClientManager.cs
diff options
context:
space:
mode:
authorJohn Hurliman2009-10-13 14:50:03 -0700
committerJohn Hurliman2009-10-13 14:50:03 -0700
commit23a334b9f54a1ef5df3b503c165e7b76b746a2b1 (patch)
tree93003db47fcd77af4085c0c49cbc1f2f0293b5eb /OpenSim/Framework/ClientManager.cs
parent* Unregister event handlers in LLUDPServer when a client logs out and disconn... (diff)
downloadopensim-SC_OLD-23a334b9f54a1ef5df3b503c165e7b76b746a2b1.zip
opensim-SC_OLD-23a334b9f54a1ef5df3b503c165e7b76b746a2b1.tar.gz
opensim-SC_OLD-23a334b9f54a1ef5df3b503c165e7b76b746a2b1.tar.bz2
opensim-SC_OLD-23a334b9f54a1ef5df3b503c165e7b76b746a2b1.tar.xz
* Rewrote ClientManager to remove Lindenisms from OpenSim core, improve performance by removing locks, and replace LLUDPClientCollection
* Removed the confusing (and LL-specific) shutdowncircuit parameter from IClientAPI.Close() * Updated the LLUDP code to only use ClientManager instead of trying to synchronize ClientManager and m_clients * Remove clients asynchronously since it is a very slow operation (including a 2000ms sleep)
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/ClientManager.cs170
1 files changed, 144 insertions, 26 deletions
diff --git a/OpenSim/Framework/ClientManager.cs b/OpenSim/Framework/ClientManager.cs
index 5ebbbc1..4edfabe 100644
--- a/OpenSim/Framework/ClientManager.cs
+++ b/OpenSim/Framework/ClientManager.cs
@@ -28,56 +28,174 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using log4net; 31using System.Net;
32using BclExtras.Collections;
32using OpenMetaverse; 33using OpenMetaverse;
33using OpenMetaverse.Packets; 34using OpenMetaverse.Packets;
34 35
35namespace OpenSim.Framework 36namespace OpenSim.Framework
36{ 37{
38 /// <summary>
39 /// Maps from client AgentID and RemoteEndPoint values to IClientAPI
40 /// references for all of the connected clients
41 /// </summary>
37 public class ClientManager 42 public class ClientManager
38 { 43 {
39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 #region IComparers
40 45
41 private Dictionary<uint, IClientAPI> m_clients = new Dictionary<uint, IClientAPI>(); 46 private sealed class UUIDComparer : IComparer<UUID>
42
43 public void Add(uint circuitCode, IClientAPI client)
44 { 47 {
45 lock (m_clients) 48 public int Compare(UUID x, UUID y)
46 m_clients.Add(circuitCode, client); 49 {
50 return x.CompareTo(y);
51 }
47 } 52 }
48 53
49 public bool Remove(uint circuitCode) 54 private sealed class IPEndPointComparer : IComparer<IPEndPoint>
50 { 55 {
51 lock (m_clients) 56 public int Compare(IPEndPoint x, IPEndPoint y)
52 return m_clients.Remove(circuitCode); 57 {
58 if (x == null && y == null)
59 return 0;
60 else if (x == null)
61 return -1;
62 else if (y == null)
63 return 1;
64
65 int result = x.Address.Address.CompareTo(y.Address.Address);
66 if (result == 0) result = x.Port.CompareTo(y.Port);
67
68 return result;
69 }
53 } 70 }
54 71
55 public bool TryGetClient(uint circuitCode, out IClientAPI user) 72 #endregion IComparers
73
74 /// <summary>An immutable dictionary mapping from <seealso cref="UUID"/>
75 /// to <seealso cref="IClientAPI"/> references</summary>
76 private ImmutableMap<UUID, IClientAPI> m_dict;
77 /// <summary>An immutable dictionary mapping from <seealso cref="IPEndPoint"/>
78 /// to <seealso cref="IClientAPI"/> references</summary>
79 private ImmutableMap<IPEndPoint, IClientAPI> m_dict2;
80 /// <summary>Immutability grants thread safety for concurrent reads and
81 /// read-writes, but not concurrent writes</summary>
82 private object m_writeLock = new object();
83
84 /// <summary>Number of clients in the collection</summary>
85 public int Count { get { return m_dict.Count; } }
86
87 /// <summary>
88 /// Default constructor
89 /// </summary>
90 public ClientManager()
56 { 91 {
57 lock (m_clients) 92 m_dict = new ImmutableMap<UUID, IClientAPI>(new UUIDComparer());
58 return m_clients.TryGetValue(circuitCode, out user); 93 m_dict2 = new ImmutableMap<IPEndPoint, IClientAPI>(new IPEndPointComparer());
59 } 94 }
60 95
61 public void ForEachClient(Action<IClientAPI> action) 96 /// <summary>
97 /// Add a client reference to the collection if it does not already
98 /// exist
99 /// </summary>
100 /// <param name="key">UUID of the client</param>
101 /// <param name="key2">Remote endpoint of the client</param>
102 /// <param name="value">Reference to the client object</param>
103 /// <returns>True if the client reference was successfully added,
104 /// otherwise false if the given key already existed in the collection</returns>
105 public bool Add(UUID key, IPEndPoint key2, IClientAPI value)
62 { 106 {
63 IClientAPI[] LocalClients; 107 lock (m_writeLock)
64 lock (m_clients)
65 { 108 {
66 LocalClients = new IClientAPI[m_clients.Count]; 109 if (!m_dict.ContainsKey(key) && !m_dict2.ContainsKey(key2))
67 m_clients.Values.CopyTo(LocalClients, 0);
68 }
69
70 for (int i = 0; i < LocalClients.Length; i++)
71 {
72 try
73 { 110 {
74 action(LocalClients[i]); 111 m_dict = m_dict.Add(key, value);
112 m_dict2 = m_dict2.Add(key2, value);
113
114 return true;
75 } 115 }
76 catch (Exception e) 116 else
77 { 117 {
78 m_log.Warn("[CLIENT]: Unable to do ForEachClient for one of the clients" + "\n Reason: " + e.ToString()); 118 return false;
79 } 119 }
80 } 120 }
81 } 121 }
122
123 /// <summary>
124 /// Remove a client from the collection
125 /// </summary>
126 /// <param name="key">UUID of the client</param>
127 /// <param name="key2">Remote endpoint of the client</param>
128 public void Remove(UUID key, IPEndPoint key2)
129 {
130 lock (m_writeLock)
131 {
132 m_dict = m_dict.Delete(key);
133 m_dict2 = m_dict2.Delete(key2);
134 }
135 }
136
137 /// <summary>
138 /// Resets the client collection
139 /// </summary>
140 public void Clear()
141 {
142 lock (m_writeLock)
143 {
144 m_dict = new ImmutableMap<UUID, IClientAPI>(new UUIDComparer());
145 m_dict2 = new ImmutableMap<IPEndPoint, IClientAPI>(new IPEndPointComparer());
146 }
147 }
148
149 /// <summary>
150 /// Checks if a UUID is in the collection
151 /// </summary>
152 /// <param name="key">UUID to check for</param>
153 /// <returns>True if the UUID was found in the collection, otherwise false</returns>
154 public bool ContainsKey(UUID key)
155 {
156 return m_dict.ContainsKey(key);
157 }
158
159 /// <summary>
160 /// Checks if an endpoint is in the collection
161 /// </summary>
162 /// <param name="key">Endpoint to check for</param>
163 /// <returns>True if the endpoint was found in the collection, otherwise false</returns>
164 public bool ContainsKey(IPEndPoint key)
165 {
166 return m_dict2.ContainsKey(key);
167 }
168
169 /// <summary>
170 /// Attempts to fetch a value out of the collection
171 /// </summary>
172 /// <param name="key">UUID of the client to retrieve</param>
173 /// <param name="value">Retrieved client, or null on lookup failure</param>
174 /// <returns>True if the lookup succeeded, otherwise false</returns>
175 public bool TryGetValue(UUID key, out IClientAPI value)
176 {
177 return m_dict.TryGetValue(key, out value);
178 }
179
180 /// <summary>
181 /// Attempts to fetch a value out of the collection
182 /// </summary>
183 /// <param name="key">Endpoint of the client to retrieve</param>
184 /// <param name="value">Retrieved client, or null on lookup failure</param>
185 /// <returns>True if the lookup succeeded, otherwise false</returns>
186 public bool TryGetValue(IPEndPoint key, out IClientAPI value)
187 {
188 return m_dict2.TryGetValue(key, out value);
189 }
190
191 /// <summary>
192 /// Performs a given task in parallel for each of the elements in the
193 /// collection
194 /// </summary>
195 /// <param name="action">Action to perform on each element</param>
196 public void ForEach(Action<IClientAPI> action)
197 {
198 Parallel.ForEach<IClientAPI>(m_dict.Values, action);
199 }
82 } 200 }
83} 201}