clockwerk-opensim-stable – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27  
28 using System;
29 using System.Collections.Generic;
30 using System.Reflection;
31 using System.Net;
32 using OpenMetaverse;
33 using OpenMetaverse.Packets;
34  
35 namespace OpenSim.Framework
36 {
37 /// <summary>
38 /// Maps from client AgentID and RemoteEndPoint values to IClientAPI
39 /// references for all of the connected clients
40 /// </summary>
41 public class ClientManager
42 {
43 /// <summary>A dictionary mapping from <seealso cref="UUID"/>
44 /// to <seealso cref="IClientAPI"/> references</summary>
45 private Dictionary<UUID, IClientAPI> m_dict1;
46 /// <summary>A dictionary mapping from <seealso cref="IPEndPoint"/>
47 /// to <seealso cref="IClientAPI"/> references</summary>
48 private Dictionary<IPEndPoint, IClientAPI> m_dict2;
49 /// <summary>An immutable collection of <seealso cref="IClientAPI"/>
50 /// references</summary>
51 private IClientAPI[] m_array;
52 /// <summary>Synchronization object for writing to the collections</summary>
53 private object m_syncRoot = new object();
54  
55 /// <summary>Number of clients in the collection</summary>
56 public int Count { get { return m_dict1.Count; } }
57  
58 /// <summary>
59 /// Default constructor
60 /// </summary>
61 public ClientManager()
62 {
63 m_dict1 = new Dictionary<UUID, IClientAPI>();
64 m_dict2 = new Dictionary<IPEndPoint, IClientAPI>();
65 m_array = new IClientAPI[0];
66 }
67  
68 /// <summary>
69 /// Add a client reference to the collection if it does not already
70 /// exist
71 /// </summary>
72 /// <param name="value">Reference to the client object</param>
73 /// <returns>True if the client reference was successfully added,
74 /// otherwise false if the given key already existed in the collection</returns>
75 public bool Add(IClientAPI value)
76 {
77 lock (m_syncRoot)
78 {
79 if (m_dict1.ContainsKey(value.AgentId) || m_dict2.ContainsKey(value.RemoteEndPoint))
80 return false;
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;
94 }
95  
96 return true;
97 }
98  
99 /// <summary>
100 /// Remove a client from the collection
101 /// </summary>
102 /// <param name="key">UUID of the client to remove</param>
103 /// <returns>True if a client was removed, or false if the given UUID
104 /// was not present in the collection</returns>
105 public bool Remove(UUID key)
106 {
107 lock (m_syncRoot)
108 {
109 IClientAPI value;
110 if (m_dict1.TryGetValue(key, out value))
111 {
112 m_dict1.Remove(key);
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;
127 return true;
128 }
129 }
130  
131 return false;
132 }
133  
134 /// <summary>
135 /// Resets the client collection
136 /// </summary>
137 public void Clear()
138 {
139 lock (m_syncRoot)
140 {
141 m_dict1.Clear();
142 m_dict2.Clear();
143 m_array = new IClientAPI[0];
144 }
145 }
146  
147 /// <summary>
148 /// Checks if a UUID is in the collection
149 /// </summary>
150 /// <param name="key">UUID to check for</param>
151 /// <returns>True if the UUID was found in the collection, otherwise false</returns>
152 public bool ContainsKey(UUID key)
153 {
154 return m_dict1.ContainsKey(key);
155 }
156  
157 /// <summary>
158 /// Checks if an endpoint is in the collection
159 /// </summary>
160 /// <param name="key">Endpoint to check for</param>
161 /// <returns>True if the endpoint was found in the collection, otherwise false</returns>
162 public bool ContainsKey(IPEndPoint key)
163 {
164 return m_dict2.ContainsKey(key);
165 }
166  
167 /// <summary>
168 /// Attempts to fetch a value out of the collection
169 /// </summary>
170 /// <param name="key">UUID of the client to retrieve</param>
171 /// <param name="value">Retrieved client, or null on lookup failure</param>
172 /// <returns>True if the lookup succeeded, otherwise false</returns>
173 public bool TryGetValue(UUID key, out IClientAPI value)
174 {
175 try { return m_dict1.TryGetValue(key, out value); }
176 catch (Exception)
177 {
178 value = null;
179 return false;
180 }
181 }
182  
183 /// <summary>
184 /// Attempts to fetch a value out of the collection
185 /// </summary>
186 /// <param name="key">Endpoint of the client to retrieve</param>
187 /// <param name="value">Retrieved client, or null on lookup failure</param>
188 /// <returns>True if the lookup succeeded, otherwise false</returns>
189 public bool TryGetValue(IPEndPoint key, out IClientAPI value)
190 {
191 try { return m_dict2.TryGetValue(key, out value); }
192 catch (Exception)
193 {
194 value = null;
195 return false;
196 }
197 }
198  
199 /// <summary>
200 /// Performs a given task in parallel for each of the elements in the
201 /// collection
202 /// </summary>
203 /// <param name="action">Action to perform on each element</param>
204 public void ForEach(Action<IClientAPI> action)
205 {
206 IClientAPI[] localArray = m_array;
207 Parallel.For(0, localArray.Length,
208 delegate(int i)
209 { action(localArray[i]); }
210 );
211 }
212  
213 /// <summary>
214 /// Performs a given task synchronously for each of the elements in
215 /// the collection
216 /// </summary>
217 /// <param name="action">Action to perform on each element</param>
218 public void ForEachSync(Action<IClientAPI> action)
219 {
220 IClientAPI[] localArray = m_array;
221 for (int i = 0; i < localArray.Length; i++)
222 action(localArray[i]);
223 }
224 }
225 }