clockwerk-opensim-stable – Blame information for rev 3
?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 | caps = new Caps(MainServer.Instance, m_scene.RegionInfo.ExternalHostName, |
||
141 | (MainServer.Instance == null) ? 0: MainServer.Instance.Port, |
||
142 | capsObjectPath, agentId, m_scene.RegionInfo.RegionName); |
||
143 | |||
144 | m_capsObjects[agentId] = caps; |
||
145 | } |
||
146 | |||
147 | m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps); |
||
148 | } |
||
149 | |||
150 | public void RemoveCaps(UUID agentId) |
||
151 | { |
||
152 | m_log.DebugFormat("[CAPS]: Remove caps for agent {0} in region {1}", agentId, m_scene.RegionInfo.RegionName); |
||
153 | lock (m_childrenSeeds) |
||
154 | { |
||
155 | if (m_childrenSeeds.ContainsKey(agentId)) |
||
156 | { |
||
157 | m_childrenSeeds.Remove(agentId); |
||
158 | } |
||
159 | } |
||
160 | |||
161 | lock (m_capsObjects) |
||
162 | { |
||
163 | if (m_capsObjects.ContainsKey(agentId)) |
||
164 | { |
||
165 | m_capsObjects[agentId].DeregisterHandlers(); |
||
166 | m_scene.EventManager.TriggerOnDeregisterCaps(agentId, m_capsObjects[agentId]); |
||
167 | m_capsObjects.Remove(agentId); |
||
168 | } |
||
169 | else |
||
170 | { |
||
171 | m_log.WarnFormat( |
||
172 | "[CAPS]: Received request to remove CAPS handler for root agent {0} in {1}, but no such CAPS handler found!", |
||
173 | agentId, m_scene.RegionInfo.RegionName); |
||
174 | } |
||
175 | } |
||
176 | } |
||
177 | |||
178 | public Caps GetCapsForUser(UUID agentId) |
||
179 | { |
||
180 | lock (m_capsObjects) |
||
181 | { |
||
182 | if (m_capsObjects.ContainsKey(agentId)) |
||
183 | { |
||
184 | return m_capsObjects[agentId]; |
||
185 | } |
||
186 | } |
||
187 | |||
188 | return null; |
||
189 | } |
||
190 | |||
191 | public void SetAgentCapsSeeds(AgentCircuitData agent) |
||
192 | { |
||
193 | lock (m_capsPaths) |
||
194 | m_capsPaths[agent.AgentID] = agent.CapsPath; |
||
195 | |||
196 | lock (m_childrenSeeds) |
||
197 | m_childrenSeeds[agent.AgentID] |
||
198 | = ((agent.ChildrenCapSeeds == null) ? new Dictionary<ulong, string>() : agent.ChildrenCapSeeds); |
||
199 | } |
||
200 | |||
201 | public string GetCapsPath(UUID agentId) |
||
202 | { |
||
203 | lock (m_capsPaths) |
||
204 | { |
||
205 | if (m_capsPaths.ContainsKey(agentId)) |
||
206 | { |
||
207 | return m_capsPaths[agentId]; |
||
208 | } |
||
209 | } |
||
210 | |||
211 | return null; |
||
212 | } |
||
213 | |||
214 | public Dictionary<ulong, string> GetChildrenSeeds(UUID agentID) |
||
215 | { |
||
216 | Dictionary<ulong, string> seeds = null; |
||
217 | |||
218 | lock (m_childrenSeeds) |
||
219 | if (m_childrenSeeds.TryGetValue(agentID, out seeds)) |
||
220 | return seeds; |
||
221 | |||
222 | return new Dictionary<ulong, string>(); |
||
223 | } |
||
224 | |||
225 | public void DropChildSeed(UUID agentID, ulong handle) |
||
226 | { |
||
227 | Dictionary<ulong, string> seeds; |
||
228 | |||
229 | lock (m_childrenSeeds) |
||
230 | { |
||
231 | if (m_childrenSeeds.TryGetValue(agentID, out seeds)) |
||
232 | { |
||
233 | seeds.Remove(handle); |
||
234 | } |
||
235 | } |
||
236 | } |
||
237 | |||
238 | public string GetChildSeed(UUID agentID, ulong handle) |
||
239 | { |
||
240 | Dictionary<ulong, string> seeds; |
||
241 | string returnval; |
||
242 | |||
243 | lock (m_childrenSeeds) |
||
244 | { |
||
245 | if (m_childrenSeeds.TryGetValue(agentID, out seeds)) |
||
246 | { |
||
247 | if (seeds.TryGetValue(handle, out returnval)) |
||
248 | return returnval; |
||
249 | } |
||
250 | } |
||
251 | |||
252 | return null; |
||
253 | } |
||
254 | |||
255 | public void SetChildrenSeed(UUID agentID, Dictionary<ulong, string> seeds) |
||
256 | { |
||
257 | //m_log.DebugFormat(" !!! Setting child seeds in {0} to {1}", m_scene.RegionInfo.RegionName, seeds.Count); |
||
258 | |||
259 | lock (m_childrenSeeds) |
||
260 | m_childrenSeeds[agentID] = seeds; |
||
261 | } |
||
262 | |||
263 | public void DumpChildrenSeeds(UUID agentID) |
||
264 | { |
||
265 | m_log.Info("================ ChildrenSeed "+m_scene.RegionInfo.RegionName+" ================"); |
||
266 | |||
267 | lock (m_childrenSeeds) |
||
268 | { |
||
269 | foreach (KeyValuePair<ulong, string> kvp in m_childrenSeeds[agentID]) |
||
270 | { |
||
271 | uint x, y; |
||
272 | Utils.LongToUInts(kvp.Key, out x, out y); |
||
273 | x = x / Constants.RegionSize; |
||
274 | y = y / Constants.RegionSize; |
||
275 | m_log.Info(" >> "+x+", "+y+": "+kvp.Value); |
||
276 | } |
||
277 | } |
||
278 | } |
||
279 | |||
280 | private void HandleShowCapsListCommand(string module, string[] cmdParams) |
||
281 | { |
||
282 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) |
||
283 | return; |
||
284 | |||
285 | StringBuilder capsReport = new StringBuilder(); |
||
286 | capsReport.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName); |
||
287 | |||
288 | lock (m_capsObjects) |
||
289 | { |
||
290 | foreach (KeyValuePair<UUID, Caps> kvp in m_capsObjects) |
||
291 | { |
||
292 | capsReport.AppendFormat("** User {0}:\n", kvp.Key); |
||
293 | Caps caps = kvp.Value; |
||
294 | |||
295 | for (IDictionaryEnumerator kvp2 = caps.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); ) |
||
296 | { |
||
297 | Uri uri = new Uri(kvp2.Value.ToString()); |
||
298 | capsReport.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery); |
||
299 | } |
||
300 | |||
301 | foreach (KeyValuePair<string, PollServiceEventArgs> kvp2 in caps.GetPollHandlers()) |
||
302 | capsReport.AppendFormat(m_showCapsCommandFormat, kvp2.Key, kvp2.Value.Url); |
||
303 | |||
304 | foreach (KeyValuePair<string, string> kvp3 in caps.ExternalCapsHandlers) |
||
305 | capsReport.AppendFormat(m_showCapsCommandFormat, kvp3.Key, kvp3.Value); |
||
306 | } |
||
307 | } |
||
308 | |||
309 | MainConsole.Instance.Output(capsReport.ToString()); |
||
310 | } |
||
311 | |||
312 | private void HandleShowCapsStatsByCapCommand(string module, string[] cmdParams) |
||
313 | { |
||
314 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) |
||
315 | return; |
||
316 | |||
317 | if (cmdParams.Length != 5 && cmdParams.Length != 6) |
||
318 | { |
||
319 | MainConsole.Instance.Output("Usage: show caps stats by cap [<cap-name>]"); |
||
320 | return; |
||
321 | } |
||
322 | |||
323 | StringBuilder sb = new StringBuilder(); |
||
324 | sb.AppendFormat("Region {0}:\n", m_scene.Name); |
||
325 | |||
326 | if (cmdParams.Length == 5) |
||
327 | { |
||
328 | BuildSummaryStatsByCapReport(sb); |
||
329 | } |
||
330 | else if (cmdParams.Length == 6) |
||
331 | { |
||
332 | BuildDetailedStatsByCapReport(sb, cmdParams[5]); |
||
333 | } |
||
334 | |||
335 | MainConsole.Instance.Output(sb.ToString()); |
||
336 | } |
||
337 | |||
338 | private void BuildDetailedStatsByCapReport(StringBuilder sb, string capName) |
||
339 | { |
||
340 | sb.AppendFormat("Capability name {0}\n", capName); |
||
341 | |||
342 | ConsoleDisplayTable cdt = new ConsoleDisplayTable(); |
||
343 | cdt.AddColumn("User Name", 34); |
||
344 | cdt.AddColumn("Req Received", 12); |
||
345 | cdt.AddColumn("Req Handled", 12); |
||
346 | cdt.Indent = 2; |
||
347 | |||
348 | Dictionary<string, int> receivedStats = new Dictionary<string, int>(); |
||
349 | Dictionary<string, int> handledStats = new Dictionary<string, int>(); |
||
350 | |||
351 | m_scene.ForEachScenePresence( |
||
352 | sp => |
||
353 | { |
||
354 | Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID); |
||
355 | |||
356 | if (caps == null) |
||
357 | return; |
||
358 | |||
359 | Dictionary<string, IRequestHandler> capsHandlers = caps.CapsHandlers.GetCapsHandlers(); |
||
360 | |||
361 | IRequestHandler reqHandler; |
||
362 | if (capsHandlers.TryGetValue(capName, out reqHandler)) |
||
363 | { |
||
364 | receivedStats[sp.Name] = reqHandler.RequestsReceived; |
||
365 | handledStats[sp.Name] = reqHandler.RequestsHandled; |
||
366 | } |
||
367 | else |
||
368 | { |
||
369 | PollServiceEventArgs pollHandler = null; |
||
370 | if (caps.TryGetPollHandler(capName, out pollHandler)) |
||
371 | { |
||
372 | receivedStats[sp.Name] = pollHandler.RequestsReceived; |
||
373 | handledStats[sp.Name] = pollHandler.RequestsHandled; |
||
374 | } |
||
375 | } |
||
376 | } |
||
377 | ); |
||
378 | |||
379 | foreach (KeyValuePair<string, int> kvp in receivedStats.OrderByDescending(kp => kp.Value)) |
||
380 | { |
||
381 | cdt.AddRow(kvp.Key, kvp.Value, handledStats[kvp.Key]); |
||
382 | } |
||
383 | |||
384 | sb.Append(cdt.ToString()); |
||
385 | } |
||
386 | |||
387 | private void BuildSummaryStatsByCapReport(StringBuilder sb) |
||
388 | { |
||
389 | ConsoleDisplayTable cdt = new ConsoleDisplayTable(); |
||
390 | cdt.AddColumn("Name", 34); |
||
391 | cdt.AddColumn("Req Received", 12); |
||
392 | cdt.AddColumn("Req Handled", 12); |
||
393 | cdt.Indent = 2; |
||
394 | |||
395 | Dictionary<string, int> receivedStats = new Dictionary<string, int>(); |
||
396 | Dictionary<string, int> handledStats = new Dictionary<string, int>(); |
||
397 | |||
398 | m_scene.ForEachScenePresence( |
||
399 | sp => |
||
400 | { |
||
401 | Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID); |
||
402 | |||
403 | if (caps == null) |
||
404 | return; |
||
405 | |||
406 | foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values) |
||
407 | { |
||
408 | string reqName = reqHandler.Name ?? ""; |
||
409 | |||
410 | if (!receivedStats.ContainsKey(reqName)) |
||
411 | { |
||
412 | receivedStats[reqName] = reqHandler.RequestsReceived; |
||
413 | handledStats[reqName] = reqHandler.RequestsHandled; |
||
414 | } |
||
415 | else |
||
416 | { |
||
417 | receivedStats[reqName] += reqHandler.RequestsReceived; |
||
418 | handledStats[reqName] += reqHandler.RequestsHandled; |
||
419 | } |
||
420 | } |
||
421 | |||
422 | foreach (KeyValuePair<string, PollServiceEventArgs> kvp in caps.GetPollHandlers()) |
||
423 | { |
||
424 | string name = kvp.Key; |
||
425 | PollServiceEventArgs pollHandler = kvp.Value; |
||
426 | |||
427 | if (!receivedStats.ContainsKey(name)) |
||
428 | { |
||
429 | receivedStats[name] = pollHandler.RequestsReceived; |
||
430 | handledStats[name] = pollHandler.RequestsHandled; |
||
431 | } |
||
432 | else |
||
433 | { |
||
434 | receivedStats[name] += pollHandler.RequestsReceived; |
||
435 | handledStats[name] += pollHandler.RequestsHandled; |
||
436 | } |
||
437 | } |
||
438 | } |
||
439 | ); |
||
440 | |||
441 | foreach (KeyValuePair<string, int> kvp in receivedStats.OrderByDescending(kp => kp.Value)) |
||
442 | cdt.AddRow(kvp.Key, kvp.Value, handledStats[kvp.Key]); |
||
443 | |||
444 | sb.Append(cdt.ToString()); |
||
445 | } |
||
446 | |||
447 | private void HandleShowCapsStatsByUserCommand(string module, string[] cmdParams) |
||
448 | { |
||
449 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) |
||
450 | return; |
||
451 | |||
452 | if (cmdParams.Length != 5 && cmdParams.Length != 7) |
||
453 | { |
||
454 | MainConsole.Instance.Output("Usage: show caps stats by user [<first-name> <last-name>]"); |
||
455 | return; |
||
456 | } |
||
457 | |||
458 | StringBuilder sb = new StringBuilder(); |
||
459 | sb.AppendFormat("Region {0}:\n", m_scene.Name); |
||
460 | |||
461 | if (cmdParams.Length == 5) |
||
462 | { |
||
463 | BuildSummaryStatsByUserReport(sb); |
||
464 | } |
||
465 | else if (cmdParams.Length == 7) |
||
466 | { |
||
467 | string firstName = cmdParams[5]; |
||
468 | string lastName = cmdParams[6]; |
||
469 | |||
470 | ScenePresence sp = m_scene.GetScenePresence(firstName, lastName); |
||
471 | |||
472 | if (sp == null) |
||
473 | return; |
||
474 | |||
475 | BuildDetailedStatsByUserReport(sb, sp); |
||
476 | } |
||
477 | |||
478 | MainConsole.Instance.Output(sb.ToString()); |
||
479 | } |
||
480 | |||
481 | private void BuildDetailedStatsByUserReport(StringBuilder sb, ScenePresence sp) |
||
482 | { |
||
483 | sb.AppendFormat("Avatar name {0}, type {1}\n", sp.Name, sp.IsChildAgent ? "child" : "root"); |
||
484 | |||
485 | ConsoleDisplayTable cdt = new ConsoleDisplayTable(); |
||
486 | cdt.AddColumn("Cap Name", 34); |
||
487 | cdt.AddColumn("Req Received", 12); |
||
488 | cdt.AddColumn("Req Handled", 12); |
||
489 | cdt.Indent = 2; |
||
490 | |||
491 | Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID); |
||
492 | |||
493 | if (caps == null) |
||
494 | return; |
||
495 | |||
496 | List<CapTableRow> capRows = new List<CapTableRow>(); |
||
497 | |||
498 | foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values) |
||
499 | capRows.Add(new CapTableRow(reqHandler.Name, reqHandler.RequestsReceived, reqHandler.RequestsHandled)); |
||
500 | |||
501 | foreach (KeyValuePair<string, PollServiceEventArgs> kvp in caps.GetPollHandlers()) |
||
502 | capRows.Add(new CapTableRow(kvp.Key, kvp.Value.RequestsReceived, kvp.Value.RequestsHandled)); |
||
503 | |||
504 | foreach (CapTableRow ctr in capRows.OrderByDescending(ctr => ctr.RequestsReceived)) |
||
505 | cdt.AddRow(ctr.Name, ctr.RequestsReceived, ctr.RequestsHandled); |
||
506 | |||
507 | sb.Append(cdt.ToString()); |
||
508 | } |
||
509 | |||
510 | private void BuildSummaryStatsByUserReport(StringBuilder sb) |
||
511 | { |
||
512 | ConsoleDisplayTable cdt = new ConsoleDisplayTable(); |
||
513 | cdt.AddColumn("Name", 32); |
||
514 | cdt.AddColumn("Type", 5); |
||
515 | cdt.AddColumn("Req Received", 12); |
||
516 | cdt.AddColumn("Req Handled", 12); |
||
517 | cdt.Indent = 2; |
||
518 | |||
519 | m_scene.ForEachScenePresence( |
||
520 | sp => |
||
521 | { |
||
522 | Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID); |
||
523 | |||
524 | if (caps == null) |
||
525 | return; |
||
526 | |||
527 | Dictionary<string, IRequestHandler> capsHandlers = caps.CapsHandlers.GetCapsHandlers(); |
||
528 | |||
529 | int totalRequestsReceived = 0; |
||
530 | int totalRequestsHandled = 0; |
||
531 | |||
532 | foreach (IRequestHandler reqHandler in capsHandlers.Values) |
||
533 | { |
||
534 | totalRequestsReceived += reqHandler.RequestsReceived; |
||
535 | totalRequestsHandled += reqHandler.RequestsHandled; |
||
536 | } |
||
537 | |||
538 | Dictionary<string, PollServiceEventArgs> capsPollHandlers = caps.GetPollHandlers(); |
||
539 | |||
540 | foreach (PollServiceEventArgs handler in capsPollHandlers.Values) |
||
541 | { |
||
542 | totalRequestsReceived += handler.RequestsReceived; |
||
543 | totalRequestsHandled += handler.RequestsHandled; |
||
544 | } |
||
545 | |||
546 | cdt.AddRow(sp.Name, sp.IsChildAgent ? "child" : "root", totalRequestsReceived, totalRequestsHandled); |
||
547 | } |
||
548 | ); |
||
549 | |||
550 | sb.Append(cdt.ToString()); |
||
551 | } |
||
552 | |||
553 | private class CapTableRow |
||
554 | { |
||
555 | public string Name { get; set; } |
||
556 | public int RequestsReceived { get; set; } |
||
557 | public int RequestsHandled { get; set; } |
||
558 | |||
559 | public CapTableRow(string name, int requestsReceived, int requestsHandled) |
||
560 | { |
||
561 | Name = name; |
||
562 | RequestsReceived = requestsReceived; |
||
563 | RequestsHandled = requestsHandled; |
||
564 | } |
||
565 | } |
||
566 | } |
||
567 | } |