opensim-development – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | eva | 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; |
||
30 | using System.Collections.Generic; |
||
31 | using System.Reflection; |
||
32 | using System.Text; |
||
33 | using Mono.Data.SqliteClient; |
||
34 | using OpenMetaverse; |
||
35 | using OpenMetaverse.StructuredData; |
||
36 | using OpenSim.Framework; |
||
37 | using OpenSim.Region.Framework.Scenes; |
||
38 | using OpenSim.Framework.Monitoring; |
||
39 | |||
40 | namespace 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(" "); |
||
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 | } |