aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/UserStatistics/ActiveConnectionsAJAX.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/OptionalModules/UserStatistics/ActiveConnectionsAJAX.cs')
-rw-r--r--OpenSim/Region/OptionalModules/UserStatistics/ActiveConnectionsAJAX.cs308
1 files changed, 308 insertions, 0 deletions
diff --git a/OpenSim/Region/OptionalModules/UserStatistics/ActiveConnectionsAJAX.cs b/OpenSim/Region/OptionalModules/UserStatistics/ActiveConnectionsAJAX.cs
new file mode 100644
index 0000000..6a1112c
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/UserStatistics/ActiveConnectionsAJAX.cs
@@ -0,0 +1,308 @@
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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using System.Text;
33using Mono.Data.SqliteClient;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Framework.Monitoring;
39
40namespace OpenSim.Region.UserStatistics
41{
42 public class ActiveConnectionsAJAX : IStatsController
43 {
44 private Vector3 DefaultNeighborPosition = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 70);
45
46 #region IStatsController Members
47
48 public string ReportName
49 {
50 get { return ""; }
51 }
52
53 public Hashtable ProcessModel(Hashtable pParams)
54 {
55 List<Scene> m_scene = (List<Scene>)pParams["Scenes"];
56
57 Hashtable nh = new Hashtable();
58 nh.Add("hdata", m_scene);
59
60 return nh;
61 }
62
63 public string RenderView(Hashtable pModelResult)
64 {
65 List<Scene> all_scenes = (List<Scene>) pModelResult["hdata"];
66
67 StringBuilder output = new StringBuilder();
68 HTMLUtil.OL_O(ref output, "");
69 foreach (Scene scene in all_scenes)
70 {
71 HTMLUtil.LI_O(ref output, String.Empty);
72 output.Append(scene.RegionInfo.RegionName);
73 HTMLUtil.OL_O(ref output, String.Empty);
74 scene.ForEachScenePresence(delegate(ScenePresence av)
75 {
76 Dictionary<string, string> queues = new Dictionary<string, string>();
77 if (av.ControllingClient is IStatsCollector)
78 {
79 IStatsCollector isClient = (IStatsCollector)av.ControllingClient;
80 queues = decodeQueueReport(isClient.Report());
81 }
82 HTMLUtil.LI_O(ref output, String.Empty);
83 output.Append(av.Name);
84 output.Append("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
85 output.Append((av.IsChildAgent ? "Child" : "Root"));
86 if (av.AbsolutePosition == DefaultNeighborPosition)
87 {
88 output.Append("<br />Position: ?");
89 }
90 else
91 {
92 output.Append(string.Format("<br /><NOBR>Position: <{0},{1},{2}></NOBR>", (int)av.AbsolutePosition.X,
93 (int)av.AbsolutePosition.Y,
94 (int)av.AbsolutePosition.Z));
95 }
96 Dictionary<string, int> throttles = DecodeClientThrottles(av.ControllingClient.GetThrottlesPacked(1));
97
98 HTMLUtil.UL_O(ref output, String.Empty);
99
100 foreach (string throttlename in throttles.Keys)
101 {
102 HTMLUtil.LI_O(ref output, String.Empty);
103 output.Append(throttlename);
104 output.Append(":");
105 output.Append(throttles[throttlename].ToString());
106 if (queues.ContainsKey(throttlename))
107 {
108 output.Append("/");
109 output.Append(queues[throttlename]);
110 }
111 HTMLUtil.LI_C(ref output);
112 }
113 if (queues.ContainsKey("Incoming") && queues.ContainsKey("Outgoing"))
114 {
115 HTMLUtil.LI_O(ref output, "red");
116 output.Append("SEND:");
117 output.Append(queues["Outgoing"]);
118 output.Append("/");
119 output.Append(queues["Incoming"]);
120 HTMLUtil.LI_C(ref output);
121 }
122
123 HTMLUtil.UL_C(ref output);
124 HTMLUtil.LI_C(ref output);
125 });
126 HTMLUtil.OL_C(ref output);
127 }
128 HTMLUtil.OL_C(ref output);
129 return output.ToString();
130 }
131
132 /// <summary>
133 /// Convert active connections information to JSON string. Returns a structure:
134 /// <pre>
135 /// {"regionName": {
136 /// "presenceName": {
137 /// "name": "presenceName",
138 /// "position": "<x,y,z>",
139 /// "isRoot": "false",
140 /// "throttle": {
141 /// },
142 /// "queue": {
143 /// }
144 /// },
145 /// ... // multiple presences in the scene
146 /// },
147 /// ... // multiple regions in the sim
148 /// }
149 ///
150 /// </pre>
151 /// </summary>
152 /// <param name="pModelResult"></param>
153 /// <returns></returns>
154 public string RenderJson(Hashtable pModelResult)
155 {
156 List<Scene> all_scenes = (List<Scene>) pModelResult["hdata"];
157
158 OSDMap regionInfo = new OSDMap();
159 foreach (Scene scene in all_scenes)
160 {
161 OSDMap sceneInfo = new OpenMetaverse.StructuredData.OSDMap();
162 List<ScenePresence> avatarInScene = scene.GetScenePresences();
163 foreach (ScenePresence av in avatarInScene)
164 {
165 OSDMap presenceInfo = new OSDMap();
166 presenceInfo.Add("Name", new OSDString(av.Name));
167
168 Dictionary<string,string> queues = new Dictionary<string, string>();
169 if (av.ControllingClient is IStatsCollector)
170 {
171 IStatsCollector isClient = (IStatsCollector) av.ControllingClient;
172 queues = decodeQueueReport(isClient.Report());
173 }
174 OSDMap queueInfo = new OpenMetaverse.StructuredData.OSDMap();
175 foreach (KeyValuePair<string, string> kvp in queues) {
176 queueInfo.Add(kvp.Key, new OSDString(kvp.Value));
177 }
178 sceneInfo.Add("queues", queueInfo);
179
180 if (av.IsChildAgent)
181 presenceInfo.Add("isRoot", new OSDString("false"));
182 else
183 presenceInfo.Add("isRoot", new OSDString("true"));
184
185 if (av.AbsolutePosition == DefaultNeighborPosition)
186 {
187 presenceInfo.Add("position", new OSDString("<0, 0, 0>"));
188 }
189 else
190 {
191 presenceInfo.Add("position", new OSDString(string.Format("<{0},{1},{2}>",
192 (int)av.AbsolutePosition.X,
193 (int) av.AbsolutePosition.Y,
194 (int) av.AbsolutePosition.Z)) );
195 }
196
197 Dictionary<string, int> throttles = DecodeClientThrottles(av.ControllingClient.GetThrottlesPacked(1));
198 OSDMap throttleInfo = new OpenMetaverse.StructuredData.OSDMap();
199 foreach (string throttlename in throttles.Keys)
200 {
201 throttleInfo.Add(throttlename, new OSDString(throttles[throttlename].ToString()));
202 }
203 presenceInfo.Add("throttle", throttleInfo);
204
205 sceneInfo.Add(av.Name, presenceInfo);
206 }
207 regionInfo.Add(scene.RegionInfo.RegionName, sceneInfo);
208 }
209 return regionInfo.ToString();
210 }
211
212 public Dictionary<string, int> DecodeClientThrottles(byte[] throttle)
213 {
214 Dictionary<string, int> returndict = new Dictionary<string, int>();
215 // From mantis http://opensimulator.org/mantis/view.php?id=1374
216 // it appears that sometimes we are receiving empty throttle byte arrays.
217 // TODO: Investigate this behaviour
218 if (throttle.Length == 0)
219 {
220 return new Dictionary<string, int>();
221 }
222
223 int tResend = -1;
224 int tLand = -1;
225 int tWind = -1;
226 int tCloud = -1;
227 int tTask = -1;
228 int tTexture = -1;
229 int tAsset = -1;
230 int tall = -1;
231 const int singlefloat = 4;
232
233 //Agent Throttle Block contains 7 single floatingpoint values.
234 int j = 0;
235
236 // Some Systems may be big endian...
237 // it might be smart to do this check more often...
238 if (!BitConverter.IsLittleEndian)
239 for (int i = 0; i < 7; i++)
240 Array.Reverse(throttle, j + i * singlefloat, singlefloat);
241
242 // values gotten from OpenMetaverse.org/wiki/Throttle. Thanks MW_
243 // bytes
244 // Convert to integer, since.. the full fp space isn't used.
245 tResend = (int)BitConverter.ToSingle(throttle, j);
246 returndict.Add("Resend", tResend);
247 j += singlefloat;
248 tLand = (int)BitConverter.ToSingle(throttle, j);
249 returndict.Add("Land", tLand);
250 j += singlefloat;
251 tWind = (int)BitConverter.ToSingle(throttle, j);
252 returndict.Add("Wind", tWind);
253 j += singlefloat;
254 tCloud = (int)BitConverter.ToSingle(throttle, j);
255 returndict.Add("Cloud", tCloud);
256 j += singlefloat;
257 tTask = (int)BitConverter.ToSingle(throttle, j);
258 returndict.Add("Task", tTask);
259 j += singlefloat;
260 tTexture = (int)BitConverter.ToSingle(throttle, j);
261 returndict.Add("Texture", tTexture);
262 j += singlefloat;
263 tAsset = (int)BitConverter.ToSingle(throttle, j);
264 returndict.Add("Asset", tAsset);
265
266 tall = tResend + tLand + tWind + tCloud + tTask + tTexture + tAsset;
267 returndict.Add("All", tall);
268
269 return returndict;
270 }
271 public Dictionary<string,string> decodeQueueReport(string rep)
272 {
273 Dictionary<string, string> returndic = new Dictionary<string, string>();
274 if (rep.Length == 79)
275 {
276 int pos = 1;
277 returndic.Add("All", rep.Substring((6 * pos), 8)); pos++;
278 returndic.Add("Incoming", rep.Substring((7 * pos), 8)); pos++;
279 returndic.Add("Outgoing", rep.Substring((7 * pos) , 8)); pos++;
280 returndic.Add("Resend", rep.Substring((7 * pos) , 8)); pos++;
281 returndic.Add("Land", rep.Substring((7 * pos) , 8)); pos++;
282 returndic.Add("Wind", rep.Substring((7 * pos) , 8)); pos++;
283 returndic.Add("Cloud", rep.Substring((7 * pos) , 8)); pos++;
284 returndic.Add("Task", rep.Substring((7 * pos) , 8)); pos++;
285 returndic.Add("Texture", rep.Substring((7 * pos), 8)); pos++;
286 returndic.Add("Asset", rep.Substring((7 * pos), 8));
287 /*
288 * return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}",
289 SendQueue.Count(),
290 IncomingPacketQueue.Count,
291 OutgoingPacketQueue.Count,
292 ResendOutgoingPacketQueue.Count,
293 LandOutgoingPacketQueue.Count,
294 WindOutgoingPacketQueue.Count,
295 CloudOutgoingPacketQueue.Count,
296 TaskOutgoingPacketQueue.Count,
297 TextureOutgoingPacketQueue.Count,
298 AssetOutgoingPacketQueue.Count);
299 */
300 }
301
302
303
304 return returndic;
305 }
306 #endregion
307 }
308}