clockwerk-opensim – Blame information for rev 1
?pathlinks?
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 copyrightD |
||
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.Linq; |
||
32 | using System.Reflection; |
||
33 | using System.Text; |
||
34 | using log4net; |
||
35 | using Nini.Config; |
||
36 | using Mono.Addins; |
||
37 | using OpenMetaverse; |
||
38 | using OpenSim.Framework; |
||
39 | using OpenSim.Framework.Console; |
||
40 | using OpenSim.Framework.Servers; |
||
41 | using OpenSim.Framework.Servers.HttpServer; |
||
42 | using OpenSim.Region.Framework.Interfaces; |
||
43 | using OpenSim.Region.Framework.Scenes; |
||
44 | using Caps=OpenSim.Framework.Capabilities.Caps; |
||
45 | |||
46 | namespace OpenSim.Region.CoreModules.Framework |
||
47 | { |
||
48 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CapabilitiesModule")] |
||
49 | public class CapabilitiesModule : INonSharedRegionModule, ICapabilitiesModule |
||
50 | { |
||
51 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
||
52 | |||
53 | private string m_showCapsCommandFormat = " {0,-38} {1,-60}\n"; |
||
54 | |||
55 | protected Scene m_scene; |
||
56 | |||
57 | /// <summary> |
||
58 | /// Each agent has its own capabilities handler. |
||
59 | /// </summary> |
||
60 | protected Dictionary<UUID, Caps> m_capsObjects = new Dictionary<UUID, Caps>(); |
||
61 | |||
62 | protected Dictionary<UUID, string> m_capsPaths = new Dictionary<UUID, string>(); |
||
63 | |||
64 | protected Dictionary<UUID, Dictionary<ulong, string>> m_childrenSeeds |
||
65 | = new Dictionary<UUID, Dictionary<ulong, string>>(); |
||
66 | |||
67 | public void Initialise(IConfigSource source) |
||
68 | { |
||
69 | } |
||
70 | |||
71 | public void AddRegion(Scene scene) |
||
72 | { |
||
73 | m_scene = scene; |
||
74 | m_scene.RegisterModuleInterface<ICapabilitiesModule>(this); |
||
75 | |||
76 | MainConsole.Instance.Commands.AddCommand( |
||
77 | "Comms", false, "show caps list", |
||
78 | "show caps list", |
||
79 | "Shows list of registered capabilities for users.", HandleShowCapsListCommand); |
||
80 | |||
81 | MainConsole.Instance.Commands.AddCommand( |
||
82 | "Comms", false, "show caps stats by user", |
||
83 | "show caps stats by user [<first-name> <last-name>]", |
||
84 | "Shows statistics on capabilities use by user.", |
||
85 | "If a user name is given, then prints a detailed breakdown of caps use ordered by number of requests received.", |
||
86 | HandleShowCapsStatsByUserCommand); |
||
87 | |||
88 | MainConsole.Instance.Commands.AddCommand( |
||
89 | "Comms", false, "show caps stats by cap", |
||
90 | "show caps stats by cap [<cap-name>]", |
||
91 | "Shows statistics on capabilities use by capability.", |
||
92 | "If a capability name is given, then prints a detailed breakdown of use by each user.", |
||
93 | HandleShowCapsStatsByCapCommand); |
||
94 | } |
||
95 | |||
96 | public void RegionLoaded(Scene scene) |
||
97 | { |
||
98 | } |
||
99 | |||
100 | public void RemoveRegion(Scene scene) |
||
101 | { |
||
102 | m_scene.UnregisterModuleInterface<ICapabilitiesModule>(this); |
||
103 | } |
||
104 | |||
105 | public void PostInitialise() |
||
106 | { |
||
107 | } |
||
108 | |||
109 | public void Close() {} |
||
110 | |||
111 | public string Name |
||
112 | { |
||
113 | get { return "Capabilities Module"; } |
||
114 | } |
||
115 | |||
116 | public Type ReplaceableInterface |
||
117 | { |
||
118 | get { return null; } |
||
119 | } |
||
120 | |||
121 | public void CreateCaps(UUID agentId) |
||
122 | { |
||
123 | if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId)) |
||
124 | return; |
||
125 | |||
126 | Caps caps; |
||
127 | String capsObjectPath = GetCapsPath(agentId); |
||
128 | |||
129 | lock (m_capsObjects) |
||
130 | { |
||
131 | if (m_capsObjects.ContainsKey(agentId)) |
||
132 | { |
||
133 | Caps oldCaps = m_capsObjects[agentId]; |
||
134 | |||
135 | //m_log.WarnFormat( |
||
136 | // "[CAPS]: Recreating caps for agent {0} in region {1}. Old caps path {2}, new caps path {3}. ", |
||
137 | // agentId, m_scene.RegionInfo.RegionName, oldCaps.CapsObjectPath, capsObjectPath); |
||
138 | } |
||
139 | |||
140 | // m_log.DebugFormat( |
||
141 | // "[CAPS]: Adding capabilities for agent {0} in {1} with path {2}", |
||
142 | // agentId, m_scene.RegionInfo.RegionName, capsObjectPath); |
||
143 | |||
144 | caps = new Caps(MainServer.Instance, m_scene.RegionInfo.ExternalHostName, |
||
145 | (MainServer.Instance == null) ? 0: MainServer.Instance.Port, |
||
146 | capsObjectPath, agentId, m_scene.RegionInfo.RegionName); |
||
147 | |||
148 | m_capsObjects[agentId] = caps; |
||
149 | } |
||
150 | |||
151 | m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps); |
||
152 | } |
||
153 | |||
154 | public void RemoveCaps(UUID agentId) |
||
155 | { |
||
156 | m_log.DebugFormat("[CAPS]: Remove caps for agent {0} in region {1}", agentId, m_scene.RegionInfo.RegionName); |
||
157 | lock (m_childrenSeeds) |
||
158 | { |
||
159 | if (m_childrenSeeds.ContainsKey(agentId)) |
||
160 | { |
||
161 | m_childrenSeeds.Remove(agentId); |
||
162 | } |
||
163 | } |
||
164 | |||
165 | lock (m_capsObjects) |
||
166 | { |
||
167 | if (m_capsObjects.ContainsKey(agentId)) |
||
168 | { |
||
169 | m_capsObjects[agentId].DeregisterHandlers(); |
||
170 | m_scene.EventManager.TriggerOnDeregisterCaps(agentId, m_capsObjects[agentId]); |
||
171 | m_capsObjects.Remove(agentId); |
||
172 | } |
||
173 | else |
||
174 | { |
||
175 | m_log.WarnFormat( |
||
176 | "[CAPS]: Received request to remove CAPS handler for root agent {0} in {1}, but no such CAPS handler found!", |
||
177 | agentId, m_scene.RegionInfo.RegionName); |
||
178 | } |
||
179 | } |
||
180 | } |
||
181 | |||
182 | public Caps GetCapsForUser(UUID agentId) |
||
183 | { |
||
184 | lock (m_capsObjects) |
||
185 | { |
||
186 | if (m_capsObjects.ContainsKey(agentId)) |
||
187 | { |
||
188 | return m_capsObjects[agentId]; |
||
189 | } |
||
190 | } |
||
191 | |||
192 | return null; |
||
193 | } |
||
194 | |||
195 | public void SetAgentCapsSeeds(AgentCircuitData agent) |
||
196 | { |
||
197 | lock (m_capsPaths) |
||
198 | m_capsPaths[agent.AgentID] = agent.CapsPath; |
||
199 | |||
200 | lock (m_childrenSeeds) |
||
201 | m_childrenSeeds[agent.AgentID] |
||
202 | = ((agent.ChildrenCapSeeds == null) ? new Dictionary<ulong, string>() : agent.ChildrenCapSeeds); |
||
203 | } |
||
204 | |||
205 | public string GetCapsPath(UUID agentId) |
||
206 | { |
||
207 | lock (m_capsPaths) |
||
208 | { |
||
209 | if (m_capsPaths.ContainsKey(agentId)) |
||
210 | { |
||
211 | return m_capsPaths[agentId]; |
||
212 | } |
||
213 | } |
||
214 | |||
215 | return null; |
||
216 | } |
||
217 | |||
218 | public Dictionary<ulong, string> GetChildrenSeeds(UUID agentID) |
||
219 | { |
||
220 | Dictionary<ulong, string> seeds = null; |
||
221 | |||
222 | lock (m_childrenSeeds) |
||
223 | if (m_childrenSeeds.TryGetValue(agentID, out seeds)) |
||
224 | return seeds; |
||
225 | |||
226 | return new Dictionary<ulong, string>(); |
||
227 | } |
||
228 | |||
229 | public void DropChildSeed(UUID agentID, ulong handle) |
||
230 | { |
||
231 | Dictionary<ulong, string> seeds; |
||
232 | |||
233 | lock (m_childrenSeeds) |
||
234 | { |
||
235 | if (m_childrenSeeds.TryGetValue(agentID, out seeds)) |
||
236 | { |
||
237 | seeds.Remove(handle); |
||
238 | } |
||
239 | } |
||
240 | } |
||
241 | |||
242 | public string GetChildSeed(UUID agentID, ulong handle) |
||
243 | { |
||
244 | Dictionary<ulong, string> seeds; |
||
245 | string returnval; |
||
246 | |||
247 | lock (m_childrenSeeds) |
||
248 | { |
||
249 | if (m_childrenSeeds.TryGetValue(agentID, out seeds)) |
||
250 | { |
||
251 | if (seeds.TryGetValue(handle, out returnval)) |
||
252 | return returnval; |
||
253 | } |
||
254 | } |
||
255 | |||
256 | return null; |
||
257 | } |
||
258 | |||
259 | public void SetChildrenSeed(UUID agentID, Dictionary<ulong, string> seeds) |
||
260 | { |
||
261 | //m_log.DebugFormat(" !!! Setting child seeds in {0} to {1}", m_scene.RegionInfo.RegionName, seeds.Count); |
||
262 | |||
263 | lock (m_childrenSeeds) |
||
264 | m_childrenSeeds[agentID] = seeds; |
||
265 | } |
||
266 | |||
267 | public void DumpChildrenSeeds(UUID agentID) |
||
268 | { |
||
269 | m_log.Info("================ ChildrenSeed "+m_scene.RegionInfo.RegionName+" ================"); |
||
270 | |||
271 | lock (m_childrenSeeds) |
||
272 | { |
||
273 | foreach (KeyValuePair<ulong, string> kvp in m_childrenSeeds[agentID]) |
||
274 | { |
||
275 | uint x, y; |
||
276 | Util.RegionHandleToRegionLoc(kvp.Key, out x, out y); |
||
277 | m_log.Info(" >> "+x+", "+y+": "+kvp.Value); |
||
278 | } |
||
279 | } |
||
280 | } |
||
281 | |||
282 | private void HandleShowCapsListCommand(string module, string[] cmdParams) |
||
283 | { |
||
284 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) |
||
285 | return; |
||
286 | |||
287 | StringBuilder capsReport = new StringBuilder(); |
||
288 | capsReport.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName); |
||
289 | |||
290 | lock (m_capsObjects) |
||
291 | { |
||
292 | foreach (KeyValuePair<UUID, Caps> kvp in m_capsObjects) |
||
293 | { |
||
294 | capsReport.AppendFormat("** User {0}:\n", kvp.Key); |
||
295 | Caps caps = kvp.Value; |
||
296 | |||
297 | for (IDictionaryEnumerator kvp2 = caps.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); ) |
||
298 | { |
||
299 | Uri uri = new Uri(kvp2.Value.ToString()); |
||
300 | capsReport.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery); |
||
301 | } |
||
302 | |||
303 | foreach (KeyValuePair<string, PollServiceEventArgs> kvp2 in caps.GetPollHandlers()) |
||
304 | capsReport.AppendFormat(m_showCapsCommandFormat, kvp2.Key, kvp2.Value.Url); |
||
305 | |||
306 | foreach (KeyValuePair<string, string> kvp3 in caps.ExternalCapsHandlers) |
||
307 | capsReport.AppendFormat(m_showCapsCommandFormat, kvp3.Key, kvp3.Value); |
||
308 | } |
||
309 | } |
||
310 | |||
311 | MainConsole.Instance.Output(capsReport.ToString()); |
||
312 | } |
||
313 | |||
314 | private void HandleShowCapsStatsByCapCommand(string module, string[] cmdParams) |
||
315 | { |
||
316 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) |
||
317 | return; |
||
318 | |||
319 | if (cmdParams.Length != 5 && cmdParams.Length != 6) |
||
320 | { |
||
321 | MainConsole.Instance.Output("Usage: show caps stats by cap [<cap-name>]"); |
||
322 | return; |
||
323 | } |
||
324 | |||
325 | StringBuilder sb = new StringBuilder(); |
||
326 | sb.AppendFormat("Region {0}:\n", m_scene.Name); |
||
327 | |||
328 | if (cmdParams.Length == 5) |
||
329 | { |
||
330 | BuildSummaryStatsByCapReport(sb); |
||
331 | } |
||
332 | else if (cmdParams.Length == 6) |
||
333 | { |
||
334 | BuildDetailedStatsByCapReport(sb, cmdParams[5]); |
||
335 | } |
||
336 | |||
337 | MainConsole.Instance.Output(sb.ToString()); |
||
338 | } |
||
339 | |||
340 | private void BuildDetailedStatsByCapReport(StringBuilder sb, string capName) |
||
341 | { |
||
342 | sb.AppendFormat("Capability name {0}\n", capName); |
||
343 | |||
344 | ConsoleDisplayTable cdt = new ConsoleDisplayTable(); |
||
345 | cdt.AddColumn("User Name", 34); |
||
346 | cdt.AddColumn("Req Received", 12); |
||
347 | cdt.AddColumn("Req Handled", 12); |
||
348 | cdt.Indent = 2; |
||
349 | |||
350 | Dictionary<string, int> receivedStats = new Dictionary<string, int>(); |
||
351 | Dictionary<string, int> handledStats = new Dictionary<string, int>(); |
||
352 | |||
353 | m_scene.ForEachScenePresence( |
||
354 | sp => |
||
355 | { |
||
356 | Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID); |
||
357 | |||
358 | if (caps == null) |
||
359 | return; |
||
360 | |||
361 | Dictionary<string, IRequestHandler> capsHandlers = caps.CapsHandlers.GetCapsHandlers(); |
||
362 | |||
363 | IRequestHandler reqHandler; |
||
364 | if (capsHandlers.TryGetValue(capName, out reqHandler)) |
||
365 | { |
||
366 | receivedStats[sp.Name] = reqHandler.RequestsReceived; |
||
367 | handledStats[sp.Name] = reqHandler.RequestsHandled; |
||
368 | } |
||
369 | else |
||
370 | { |
||
371 | PollServiceEventArgs pollHandler = null; |
||
372 | if (caps.TryGetPollHandler(capName, out pollHandler)) |
||
373 | { |
||
374 | receivedStats[sp.Name] = pollHandler.RequestsReceived; |
||
375 | handledStats[sp.Name] = pollHandler.RequestsHandled; |
||
376 | } |
||
377 | } |
||
378 | } |
||
379 | ); |
||
380 | |||
381 | foreach (KeyValuePair<string, int> kvp in receivedStats.OrderByDescending(kp => kp.Value)) |
||
382 | { |
||
383 | cdt.AddRow(kvp.Key, kvp.Value, handledStats[kvp.Key]); |
||
384 | } |
||
385 | |||
386 | sb.Append(cdt.ToString()); |
||
387 | } |
||
388 | |||
389 | private void BuildSummaryStatsByCapReport(StringBuilder sb) |
||
390 | { |
||
391 | ConsoleDisplayTable cdt = new ConsoleDisplayTable(); |
||
392 | cdt.AddColumn("Name", 34); |
||
393 | cdt.AddColumn("Req Received", 12); |
||
394 | cdt.AddColumn("Req Handled", 12); |
||
395 | cdt.Indent = 2; |
||
396 | |||
397 | Dictionary<string, int> receivedStats = new Dictionary<string, int>(); |
||
398 | Dictionary<string, int> handledStats = new Dictionary<string, int>(); |
||
399 | |||
400 | m_scene.ForEachScenePresence( |
||
401 | sp => |
||
402 | { |
||
403 | Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID); |
||
404 | |||
405 | if (caps == null) |
||
406 | return; |
||
407 | |||
408 | foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values) |
||
409 | { |
||
410 | string reqName = reqHandler.Name ?? ""; |
||
411 | |||
412 | if (!receivedStats.ContainsKey(reqName)) |
||
413 | { |
||
414 | receivedStats[reqName] = reqHandler.RequestsReceived; |
||
415 | handledStats[reqName] = reqHandler.RequestsHandled; |
||
416 | } |
||
417 | else |
||
418 | { |
||
419 | receivedStats[reqName] += reqHandler.RequestsReceived; |
||
420 | handledStats[reqName] += reqHandler.RequestsHandled; |
||
421 | } |
||
422 | } |
||
423 | |||
424 | foreach (KeyValuePair<string, PollServiceEventArgs> kvp in caps.GetPollHandlers()) |
||
425 | { |
||
426 | string name = kvp.Key; |
||
427 | PollServiceEventArgs pollHandler = kvp.Value; |
||
428 | |||
429 | if (!receivedStats.ContainsKey(name)) |
||
430 | { |
||
431 | receivedStats[name] = pollHandler.RequestsReceived; |
||
432 | handledStats[name] = pollHandler.RequestsHandled; |
||
433 | } |
||
434 | else |
||
435 | { |
||
436 | receivedStats[name] += pollHandler.RequestsReceived; |
||
437 | handledStats[name] += pollHandler.RequestsHandled; |
||
438 | } |
||
439 | } |
||
440 | } |
||
441 | ); |
||
442 | |||
443 | foreach (KeyValuePair<string, int> kvp in receivedStats.OrderByDescending(kp => kp.Value)) |
||
444 | cdt.AddRow(kvp.Key, kvp.Value, handledStats[kvp.Key]); |
||
445 | |||
446 | sb.Append(cdt.ToString()); |
||
447 | } |
||
448 | |||
449 | private void HandleShowCapsStatsByUserCommand(string module, string[] cmdParams) |
||
450 | { |
||
451 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) |
||
452 | return; |
||
453 | |||
454 | if (cmdParams.Length != 5 && cmdParams.Length != 7) |
||
455 | { |
||
456 | MainConsole.Instance.Output("Usage: show caps stats by user [<first-name> <last-name>]"); |
||
457 | return; |
||
458 | } |
||
459 | |||
460 | StringBuilder sb = new StringBuilder(); |
||
461 | sb.AppendFormat("Region {0}:\n", m_scene.Name); |
||
462 | |||
463 | if (cmdParams.Length == 5) |
||
464 | { |
||
465 | BuildSummaryStatsByUserReport(sb); |
||
466 | } |
||
467 | else if (cmdParams.Length == 7) |
||
468 | { |
||
469 | string firstName = cmdParams[5]; |
||
470 | string lastName = cmdParams[6]; |
||
471 | |||
472 | ScenePresence sp = m_scene.GetScenePresence(firstName, lastName); |
||
473 | |||
474 | if (sp == null) |
||
475 | return; |
||
476 | |||
477 | BuildDetailedStatsByUserReport(sb, sp); |
||
478 | } |
||
479 | |||
480 | MainConsole.Instance.Output(sb.ToString()); |
||
481 | } |
||
482 | |||
483 | private void BuildDetailedStatsByUserReport(StringBuilder sb, ScenePresence sp) |
||
484 | { |
||
485 | sb.AppendFormat("Avatar name {0}, type {1}\n", sp.Name, sp.IsChildAgent ? "child" : "root"); |
||
486 | |||
487 | ConsoleDisplayTable cdt = new ConsoleDisplayTable(); |
||
488 | cdt.AddColumn("Cap Name", 34); |
||
489 | cdt.AddColumn("Req Received", 12); |
||
490 | cdt.AddColumn("Req Handled", 12); |
||
491 | cdt.Indent = 2; |
||
492 | |||
493 | Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID); |
||
494 | |||
495 | if (caps == null) |
||
496 | return; |
||
497 | |||
498 | List<CapTableRow> capRows = new List<CapTableRow>(); |
||
499 | |||
500 | foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values) |
||
501 | capRows.Add(new CapTableRow(reqHandler.Name, reqHandler.RequestsReceived, reqHandler.RequestsHandled)); |
||
502 | |||
503 | foreach (KeyValuePair<string, PollServiceEventArgs> kvp in caps.GetPollHandlers()) |
||
504 | capRows.Add(new CapTableRow(kvp.Key, kvp.Value.RequestsReceived, kvp.Value.RequestsHandled)); |
||
505 | |||
506 | foreach (CapTableRow ctr in capRows.OrderByDescending(ctr => ctr.RequestsReceived)) |
||
507 | cdt.AddRow(ctr.Name, ctr.RequestsReceived, ctr.RequestsHandled); |
||
508 | |||
509 | sb.Append(cdt.ToString()); |
||
510 | } |
||
511 | |||
512 | private void BuildSummaryStatsByUserReport(StringBuilder sb) |
||
513 | { |
||
514 | ConsoleDisplayTable cdt = new ConsoleDisplayTable(); |
||
515 | cdt.AddColumn("Name", 32); |
||
516 | cdt.AddColumn("Type", 5); |
||
517 | cdt.AddColumn("Req Received", 12); |
||
518 | cdt.AddColumn("Req Handled", 12); |
||
519 | cdt.Indent = 2; |
||
520 | |||
521 | m_scene.ForEachScenePresence( |
||
522 | sp => |
||
523 | { |
||
524 | Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID); |
||
525 | |||
526 | if (caps == null) |
||
527 | return; |
||
528 | |||
529 | Dictionary<string, IRequestHandler> capsHandlers = caps.CapsHandlers.GetCapsHandlers(); |
||
530 | |||
531 | int totalRequestsReceived = 0; |
||
532 | int totalRequestsHandled = 0; |
||
533 | |||
534 | foreach (IRequestHandler reqHandler in capsHandlers.Values) |
||
535 | { |
||
536 | totalRequestsReceived += reqHandler.RequestsReceived; |
||
537 | totalRequestsHandled += reqHandler.RequestsHandled; |
||
538 | } |
||
539 | |||
540 | Dictionary<string, PollServiceEventArgs> capsPollHandlers = caps.GetPollHandlers(); |
||
541 | |||
542 | foreach (PollServiceEventArgs handler in capsPollHandlers.Values) |
||
543 | { |
||
544 | totalRequestsReceived += handler.RequestsReceived; |
||
545 | totalRequestsHandled += handler.RequestsHandled; |
||
546 | } |
||
547 | |||
548 | cdt.AddRow(sp.Name, sp.IsChildAgent ? "child" : "root", totalRequestsReceived, totalRequestsHandled); |
||
549 | } |
||
550 | ); |
||
551 | |||
552 | sb.Append(cdt.ToString()); |
||
553 | } |
||
554 | |||
555 | private class CapTableRow |
||
556 | { |
||
557 | public string Name { get; set; } |
||
558 | public int RequestsReceived { get; set; } |
||
559 | public int RequestsHandled { get; set; } |
||
560 | |||
561 | public CapTableRow(string name, int requestsReceived, int requestsHandled) |
||
562 | { |
||
563 | Name = name; |
||
564 | RequestsReceived = requestsReceived; |
||
565 | RequestsHandled = requestsHandled; |
||
566 | } |
||
567 | } |
||
568 | } |
||
569 | } |