aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs')
-rw-r--r--OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs330
1 files changed, 330 insertions, 0 deletions
diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
new file mode 100644
index 0000000..480df31
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
@@ -0,0 +1,330 @@
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.Generic;
30using System.Reflection;
31using System.Text;
32using log4net;
33using Mono.Addins;
34using Nini.Config;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Framework.Console;
38using OpenSim.Framework.Statistics;
39using OpenSim.Region.ClientStack.LindenUDP;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42
43namespace OpenSim.Region.CoreModules.UDP.Linden
44{
45 /// <summary>
46 /// A module that just holds commands for inspecting the current state of the Linden UDP stack.
47 /// </summary>
48 /// <remarks>
49 /// All actual client stack functionality remains in OpenSim.Region.ClientStack.LindenUDP
50 /// </remarks>
51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LindenUDPInfoModule")]
52 public class LindenUDPInfoModule : ISharedRegionModule
53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 protected Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
57
58 public string Name { get { return "Linden UDP Module"; } }
59
60 public Type ReplaceableInterface { get { return null; } }
61
62 public void Initialise(IConfigSource source)
63 {
64// m_log.DebugFormat("[LINDEN UDP INFO MODULE]: INITIALIZED MODULE");
65 }
66
67 public void PostInitialise()
68 {
69// m_log.DebugFormat("[LINDEN UDP INFO MODULE]: POST INITIALIZED MODULE");
70 }
71
72 public void Close()
73 {
74// m_log.DebugFormat("[LINDEN UDP INFO MODULE]: CLOSED MODULE");
75 }
76
77 public void AddRegion(Scene scene)
78 {
79// m_log.DebugFormat("[LINDEN UDP INFO MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
80
81 lock (m_scenes)
82 m_scenes[scene.RegionInfo.RegionID] = scene;
83
84 scene.AddCommand(
85 this, "show queues",
86 "show queues [full]",
87 "Show queue data for each client",
88 "Without the 'full' option, only root agents are shown."
89 + " With the 'full' option child agents are also shown.",
90 ShowQueuesReport);
91
92 scene.AddCommand(
93 this, "show throttles",
94 "show throttles [full]",
95 "Show throttle settings for each client and for the server overall",
96 "Without the 'full' option, only root agents are shown."
97 + " With the 'full' option child agents are also shown.",
98 ShowThrottlesReport);
99 }
100
101 public void RemoveRegion(Scene scene)
102 {
103// m_log.DebugFormat("[LINDEN UDP INFO MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
104
105 lock (m_scenes)
106 m_scenes.Remove(scene.RegionInfo.RegionID);
107 }
108
109 public void RegionLoaded(Scene scene)
110 {
111// m_log.DebugFormat("[LINDEN UDP INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
112 }
113
114 protected void ShowQueuesReport(string module, string[] cmd)
115 {
116 MainConsole.Instance.Output(GetQueuesReport(cmd));
117 }
118
119 protected void ShowThrottlesReport(string module, string[] cmd)
120 {
121 MainConsole.Instance.Output(GetThrottlesReport(cmd));
122 }
123
124 /// <summary>
125 /// Generate UDP Queue data report for each client
126 /// </summary>
127 /// <param name="showParams"></param>
128 /// <returns></returns>
129 protected string GetQueuesReport(string[] showParams)
130 {
131 bool showChildren = false;
132
133 if (showParams.Length > 2 && showParams[2] == "full")
134 showChildren = true;
135
136 StringBuilder report = new StringBuilder();
137
138 int columnPadding = 2;
139 int maxNameLength = 18;
140 int maxRegionNameLength = 14;
141 int maxTypeLength = 4;
142 int totalInfoFieldsLength = maxNameLength + columnPadding + maxRegionNameLength + columnPadding + maxTypeLength + columnPadding;
143
144 report.AppendFormat("{0,-" + maxNameLength + "}{1,-" + columnPadding + "}", "User", "");
145 report.AppendFormat("{0,-" + maxRegionNameLength + "}{1,-" + columnPadding + "}", "Region", "");
146 report.AppendFormat("{0,-" + maxTypeLength + "}{1,-" + columnPadding + "}", "Type", "");
147
148 report.AppendFormat(
149 "{0,7} {1,7} {2,9} {3,8} {4,7} {5,7} {6,7} {7,7} {8,9} {9,7} {10,7}\n",
150 "Pkts",
151 "Pkts",
152 "Bytes",
153 "Pkts",
154 "Pkts",
155 "Pkts",
156 "Pkts",
157 "Pkts",
158 "Pkts",
159 "Pkts",
160 "Pkts");
161
162 report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", "");
163 report.AppendFormat(
164 "{0,7} {1,7} {2,9} {3,8} {4,7} {5,7} {6,7} {7,7} {8,9} {9,7} {10,7}\n",
165 "Out",
166 "In",
167 "Unacked",
168 "Resend",
169 "Land",
170 "Wind",
171 "Cloud",
172 "Task",
173 "Texture",
174 "Asset",
175 "State");
176
177 lock (m_scenes)
178 {
179 foreach (Scene scene in m_scenes.Values)
180 {
181 scene.ForEachClient(
182 delegate(IClientAPI client)
183 {
184 if (client is IStatsCollector)
185 {
186 bool isChild = scene.PresenceChildStatus(client.AgentId);
187 if (isChild && !showChildren)
188 return;
189
190 string name = client.Name;
191 string regionName = scene.RegionInfo.RegionName;
192
193 report.AppendFormat(
194 "{0,-" + maxNameLength + "}{1,-" + columnPadding + "}",
195 name.Length > maxNameLength ? name.Substring(0, maxNameLength) : name, "");
196 report.AppendFormat(
197 "{0,-" + maxRegionNameLength + "}{1,-" + columnPadding + "}",
198 regionName.Length > maxRegionNameLength ? regionName.Substring(0, maxRegionNameLength) : regionName, "");
199 report.AppendFormat(
200 "{0,-" + maxTypeLength + "}{1,-" + columnPadding + "}",
201 isChild ? "Cd" : "Rt", "");
202
203 IStatsCollector stats = (IStatsCollector)client;
204
205 report.AppendLine(stats.Report());
206 }
207 });
208 }
209 }
210
211 return report.ToString();
212 }
213
214 /// <summary>
215 /// Show throttle data
216 /// </summary>
217 /// <param name="showParams"></param>
218 /// <returns></returns>
219 protected string GetThrottlesReport(string[] showParams)
220 {
221 bool showChildren = false;
222
223 if (showParams.Length > 2 && showParams[2] == "full")
224 showChildren = true;
225
226 StringBuilder report = new StringBuilder();
227
228 int columnPadding = 2;
229 int maxNameLength = 18;
230 int maxRegionNameLength = 14;
231 int maxTypeLength = 4;
232 int totalInfoFieldsLength = maxNameLength + columnPadding + maxRegionNameLength + columnPadding + maxTypeLength + columnPadding;
233
234 report.AppendFormat("{0,-" + maxNameLength + "}{1,-" + columnPadding + "}", "User", "");
235 report.AppendFormat("{0,-" + maxRegionNameLength + "}{1,-" + columnPadding + "}", "Region", "");
236 report.AppendFormat("{0,-" + maxTypeLength + "}{1,-" + columnPadding + "}", "Type\n", "");
237
238 bool firstClient = true;
239
240 lock (m_scenes)
241 {
242 foreach (Scene scene in m_scenes.Values)
243 {
244 scene.ForEachClient(
245 delegate(IClientAPI client)
246 {
247 if (client is LLClientView)
248 {
249 LLClientView llClient = client as LLClientView;
250
251 if (firstClient)
252 {
253 report.AppendLine(GetServerThrottlesReport(llClient.UDPServer, scene));
254 firstClient = false;
255 }
256
257 bool isChild = scene.PresenceChildStatus(client.AgentId);
258 if (isChild && !showChildren)
259 return;
260
261 string name = client.Name;
262 string regionName = scene.RegionInfo.RegionName;
263
264 LLUDPClient llUdpClient = llClient.UDPClient;
265 ClientInfo ci = llUdpClient.GetClientInfo();
266
267 report.AppendFormat(
268 "{0,-" + maxNameLength + "}{1,-" + columnPadding + "}",
269 name.Length > maxNameLength ? name.Substring(0, maxNameLength) : name, "");
270 report.AppendFormat(
271 "{0,-" + maxRegionNameLength + "}{1,-" + columnPadding + "}",
272 regionName.Length > maxRegionNameLength ? regionName.Substring(0, maxRegionNameLength) : regionName, "");
273 report.AppendFormat(
274 "{0,-" + maxTypeLength + "}{1,-" + columnPadding + "}",
275 isChild ? "Cd" : "Rt", "");
276
277 report.Append((ci.totalThrottle * 8) / 1000 + " ");
278 report.Append((ci.resendThrottle * 8) / 1000 + " ");
279 report.Append((ci.landThrottle * 8) / 1000 + " ");
280 report.Append((ci.windThrottle * 8) / 1000 + " ");
281 report.Append((ci.cloudThrottle * 8) / 1000 + " ");
282 report.Append((ci.taskThrottle * 8) / 1000 + " ");
283 report.Append((ci.textureThrottle * 8) / 1000 + " ");
284 report.Append((ci.assetThrottle * 8) / 1000 + " ");
285
286 report.AppendLine();
287 }
288 });
289 }
290 }
291
292 return report.ToString();
293 }
294
295 protected string GetServerThrottlesReport(LLUDPServer udpServer, Scene scene)
296 {
297 StringBuilder report = new StringBuilder();
298
299 int columnPadding = 2;
300 int maxNameLength = 18;
301 int maxRegionNameLength = 14;
302 int maxTypeLength = 4;
303 int totalInfoFieldsLength = maxNameLength + columnPadding + maxRegionNameLength + columnPadding + maxTypeLength + columnPadding;
304
305 string name = "SERVER LIMITS";
306 string regionName = scene.RegionInfo.RegionName;
307
308 report.AppendFormat(
309 "{0,-" + maxNameLength + "}{1,-" + columnPadding + "}",
310 name.Length > maxNameLength ? name.Substring(0, maxNameLength) : name, "");
311 report.AppendFormat(
312 "{0,-" + maxRegionNameLength + "}{1,-" + columnPadding + "}",
313 regionName.Length > maxRegionNameLength ? regionName.Substring(0, maxRegionNameLength) : regionName, "");
314 report.AppendFormat(
315 "{0,-" + maxTypeLength + "}{1,-" + columnPadding + "}", "n/a", "");
316
317 ThrottleRates throttleRates = udpServer.ThrottleRates;
318 report.Append("n/a");
319 report.Append((throttleRates.ResendLimit * 8) / 1000 + " ");
320 report.Append((throttleRates.LandLimit * 8) / 1000 + " ");
321 report.Append((throttleRates.WindLimit * 8) / 1000 + " ");
322 report.Append((throttleRates.CloudLimit * 8) / 1000 + " ");
323 report.Append((throttleRates.TaskLimit * 8) / 1000 + " ");
324 report.Append((throttleRates.TextureLimit * 8) / 1000 + " ");
325 report.Append((throttleRates.AssetLimit * 8) / 1000 + " ");
326
327 return report.ToString();
328 }
329 }
330} \ No newline at end of file