aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJohn Hurliman2009-10-14 14:25:58 -0700
committerJohn Hurliman2009-10-14 14:25:58 -0700
commit1e9e9df0b3c2c6fad5e94db96c799bb31c193af1 (patch)
tree383ef98b9ec98793103cbf21235df80523ce9e71
parent* Added the "show connections" command to print out all of the currently trac... (diff)
downloadopensim-SC-1e9e9df0b3c2c6fad5e94db96c799bb31c193af1.zip
opensim-SC-1e9e9df0b3c2c6fad5e94db96c799bb31c193af1.tar.gz
opensim-SC-1e9e9df0b3c2c6fad5e94db96c799bb31c193af1.tar.bz2
opensim-SC-1e9e9df0b3c2c6fad5e94db96c799bb31c193af1.tar.xz
* Switched to a plain lock for the ClientManager collections and protected the TryGetValues with try/catch instead of a lock
* Added ClientManager.ForEachSync() for operations that need to run synchronously, such as "show connections"
-rw-r--r--OpenSim/Framework/ClientManager.cs150
-rw-r--r--OpenSim/Region/Application/OpenSim.cs2
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs4
3 files changed, 85 insertions, 71 deletions
diff --git a/OpenSim/Framework/ClientManager.cs b/OpenSim/Framework/ClientManager.cs
index 367bc6a..61b59e7 100644
--- a/OpenSim/Framework/ClientManager.cs
+++ b/OpenSim/Framework/ClientManager.cs
@@ -29,7 +29,6 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Net; 31using System.Net;
32using BclExtras.Collections;
33using OpenMetaverse; 32using OpenMetaverse;
34using OpenMetaverse.Packets; 33using OpenMetaverse.Packets;
35 34
@@ -41,56 +40,29 @@ namespace OpenSim.Framework
41 /// </summary> 40 /// </summary>
42 public class ClientManager 41 public class ClientManager
43 { 42 {
44 #region IComparers 43 /// <summary>A dictionary mapping from <seealso cref="UUID"/>
45
46 private sealed class UUIDComparer : IComparer<UUID>
47 {
48 public int Compare(UUID x, UUID y)
49 {
50 return x.CompareTo(y);
51 }
52 }
53
54 private sealed class IPEndPointComparer : IComparer<IPEndPoint>
55 {
56 public int Compare(IPEndPoint x, IPEndPoint y)
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 }
70 }
71
72 #endregion IComparers
73
74 /// <summary>An immutable dictionary mapping from <seealso cref="UUID"/>
75 /// to <seealso cref="IClientAPI"/> references</summary> 44 /// to <seealso cref="IClientAPI"/> references</summary>
76 private ImmutableMap<UUID, IClientAPI> m_dict; 45 private Dictionary<UUID, IClientAPI> m_dict1;
77 /// <summary>An immutable dictionary mapping from <seealso cref="IPEndPoint"/> 46 /// <summary>A dictionary mapping from <seealso cref="IPEndPoint"/>
78 /// to <seealso cref="IClientAPI"/> references</summary> 47 /// to <seealso cref="IClientAPI"/> references</summary>
79 private ImmutableMap<IPEndPoint, IClientAPI> m_dict2; 48 private Dictionary<IPEndPoint, IClientAPI> m_dict2;
80 /// <summary>Immutability grants thread safety for concurrent reads and 49 /// <summary>An immutable collection of <seealso cref="IClientAPI"/>
81 /// read-writes, but not concurrent writes</summary> 50 /// references</summary>
82 private object m_writeLock = new object(); 51 private IClientAPI[] m_array;
52 /// <summary>Synchronization object for writing to the collections</summary>
53 private object m_syncRoot = new object();
83 54
84 /// <summary>Number of clients in the collection</summary> 55 /// <summary>Number of clients in the collection</summary>
85 public int Count { get { return m_dict.Count; } } 56 public int Count { get { return m_dict1.Count; } }
86 57
87 /// <summary> 58 /// <summary>
88 /// Default constructor 59 /// Default constructor
89 /// </summary> 60 /// </summary>
90 public ClientManager() 61 public ClientManager()
91 { 62 {
92 m_dict = new ImmutableMap<UUID, IClientAPI>(new UUIDComparer()); 63 m_dict1 = new Dictionary<UUID, IClientAPI>();
93 m_dict2 = new ImmutableMap<IPEndPoint, IClientAPI>(new IPEndPointComparer()); 64 m_dict2 = new Dictionary<IPEndPoint, IClientAPI>();
65 m_array = new IClientAPI[0];
94 } 66 }
95 67
96 /// <summary> 68 /// <summary>
@@ -102,20 +74,26 @@ namespace OpenSim.Framework
102 /// otherwise false if the given key already existed in the collection</returns> 74 /// otherwise false if the given key already existed in the collection</returns>
103 public bool Add(IClientAPI value) 75 public bool Add(IClientAPI value)
104 { 76 {
105 lock (m_writeLock) 77 lock (m_syncRoot)
106 { 78 {
107 if (!m_dict.ContainsKey(value.AgentId) && !m_dict2.ContainsKey(value.RemoteEndPoint)) 79 if (m_dict1.ContainsKey(value.AgentId) || m_dict2.ContainsKey(value.RemoteEndPoint))
108 {
109 m_dict = m_dict.Add(value.AgentId, value);
110 m_dict2 = m_dict2.Add(value.RemoteEndPoint, value);
111
112 return true;
113 }
114 else
115 {
116 return false; 80 return false;
117 } 81
82 m_dict1[value.AgentId] = value;
83 m_dict2[value.RemoteEndPoint] = value;
84
85 IClientAPI[] oldArray = m_array;
86 int oldLength = oldArray.Length;
87
88 IClientAPI[] newArray = new IClientAPI[oldLength + 1];
89 for (int i = 0; i < oldLength; i++)
90 newArray[i] = oldArray[i];
91 newArray[oldLength] = value;
92
93 m_array = newArray;
118 } 94 }
95
96 return true;
119 } 97 }
120 98
121 /// <summary> 99 /// <summary>
@@ -126,21 +104,31 @@ namespace OpenSim.Framework
126 /// was not present in the collection</returns> 104 /// was not present in the collection</returns>
127 public bool Remove(UUID key) 105 public bool Remove(UUID key)
128 { 106 {
129 lock (m_writeLock) 107 lock (m_syncRoot)
130 { 108 {
131 IClientAPI client; 109 IClientAPI value;
132 110 if (m_dict1.TryGetValue(key, out value))
133 if (m_dict.TryGetValue(key, out client))
134 { 111 {
135 m_dict = m_dict.Delete(key); 112 m_dict1.Remove(key);
136 m_dict2 = m_dict2.Delete(client.RemoteEndPoint); 113 m_dict2.Remove(value.RemoteEndPoint);
114
115 IClientAPI[] oldArray = m_array;
116 int oldLength = oldArray.Length;
117
118 IClientAPI[] newArray = new IClientAPI[oldLength - 1];
119 int j = 0;
120 for (int i = 0; i < oldLength; i++)
121 {
122 if (oldArray[i] != value)
123 newArray[j++] = oldArray[i];
124 }
125
126 m_array = newArray;
137 return true; 127 return true;
138 } 128 }
139 else
140 {
141 return false;
142 }
143 } 129 }
130
131 return false;
144 } 132 }
145 133
146 /// <summary> 134 /// <summary>
@@ -148,10 +136,11 @@ namespace OpenSim.Framework
148 /// </summary> 136 /// </summary>
149 public void Clear() 137 public void Clear()
150 { 138 {
151 lock (m_writeLock) 139 lock (m_syncRoot)
152 { 140 {
153 m_dict = new ImmutableMap<UUID, IClientAPI>(new UUIDComparer()); 141 m_dict1.Clear();
154 m_dict2 = new ImmutableMap<IPEndPoint, IClientAPI>(new IPEndPointComparer()); 142 m_dict2.Clear();
143 m_array = new IClientAPI[0];
155 } 144 }
156 } 145 }
157 146
@@ -162,7 +151,7 @@ namespace OpenSim.Framework
162 /// <returns>True if the UUID was found in the collection, otherwise false</returns> 151 /// <returns>True if the UUID was found in the collection, otherwise false</returns>
163 public bool ContainsKey(UUID key) 152 public bool ContainsKey(UUID key)
164 { 153 {
165 return m_dict.ContainsKey(key); 154 return m_dict1.ContainsKey(key);
166 } 155 }
167 156
168 /// <summary> 157 /// <summary>
@@ -183,7 +172,12 @@ namespace OpenSim.Framework
183 /// <returns>True if the lookup succeeded, otherwise false</returns> 172 /// <returns>True if the lookup succeeded, otherwise false</returns>
184 public bool TryGetValue(UUID key, out IClientAPI value) 173 public bool TryGetValue(UUID key, out IClientAPI value)
185 { 174 {
186 return m_dict.TryGetValue(key, out value); 175 try { return m_dict1.TryGetValue(key, out value); }
176 catch (Exception)
177 {
178 value = null;
179 return false;
180 }
187 } 181 }
188 182
189 /// <summary> 183 /// <summary>
@@ -194,7 +188,12 @@ namespace OpenSim.Framework
194 /// <returns>True if the lookup succeeded, otherwise false</returns> 188 /// <returns>True if the lookup succeeded, otherwise false</returns>
195 public bool TryGetValue(IPEndPoint key, out IClientAPI value) 189 public bool TryGetValue(IPEndPoint key, out IClientAPI value)
196 { 190 {
197 return m_dict2.TryGetValue(key, out value); 191 try { return m_dict2.TryGetValue(key, out value); }
192 catch (Exception)
193 {
194 value = null;
195 return false;
196 }
198 } 197 }
199 198
200 /// <summary> 199 /// <summary>
@@ -204,7 +203,20 @@ namespace OpenSim.Framework
204 /// <param name="action">Action to perform on each element</param> 203 /// <param name="action">Action to perform on each element</param>
205 public void ForEach(Action<IClientAPI> action) 204 public void ForEach(Action<IClientAPI> action)
206 { 205 {
207 Parallel.ForEach<IClientAPI>(m_dict.Values, action); 206 IClientAPI[] localArray = m_array;
207 Parallel.ForEach<IClientAPI>(localArray, action);
208 }
209
210 /// <summary>
211 /// Performs a given task synchronously for each of the elements in
212 /// the collection
213 /// </summary>
214 /// <param name="action">Action to perform on each element</param>
215 public void ForEachSync(Action<IClientAPI> action)
216 {
217 IClientAPI[] localArray = m_array;
218 for (int i = 0; i < localArray.Length; i++)
219 action(localArray[i]);
208 } 220 }
209 } 221 }
210} 222}
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 0fcc21e..ca6a2a3 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -933,7 +933,7 @@ namespace OpenSim
933 m_sceneManager.ForEachScene( 933 m_sceneManager.ForEachScene(
934 delegate(Scene scene) 934 delegate(Scene scene)
935 { 935 {
936 scene.ClientManager.ForEach( 936 scene.ClientManager.ForEachSync(
937 delegate(IClientAPI client) 937 delegate(IClientAPI client)
938 { 938 {
939 connections.AppendFormat("{0}: {1} ({2}) from {3} on circuit {4}\n", 939 connections.AppendFormat("{0}: {1} ({2}) from {3} on circuit {4}\n",
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 384eda7..09845d6 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -152,7 +152,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
152 m_throttleRates = new ThrottleRates(configSource); 152 m_throttleRates = new ThrottleRates(configSource);
153 } 153 }
154 154
155 public new void Start() 155 public void Start()
156 { 156 {
157 if (m_scene == null) 157 if (m_scene == null)
158 throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); 158 throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference");
@@ -817,6 +817,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
817 private void LogoutHandler(IClientAPI client) 817 private void LogoutHandler(IClientAPI client)
818 { 818 {
819 client.SendLogoutPacket(); 819 client.SendLogoutPacket();
820 if (client.IsActive)
821 RemoveClient(((LLClientView)client).UDPClient);
820 } 822 }
821 } 823 }
822} 824}