aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Monitoring/Stats
diff options
context:
space:
mode:
authoronefang2019-05-19 21:24:15 +1000
committeronefang2019-05-19 21:24:15 +1000
commit5e4d6cab00cb29cd088ab7b62ab13aff103b64cb (patch)
treea9fbc62df9eb2d1d9ba2698d8552eae71eca20d8 /OpenSim/Framework/Monitoring/Stats
parentAdd a build script. (diff)
downloadopensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.zip
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.gz
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.bz2
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.xz
Dump OpenSim 0.9.0.1 into it's own branch.
Diffstat (limited to '')
-rwxr-xr-x[-rw-r--r--]OpenSim/Framework/Monitoring/Stats/CounterStat.cs0
-rwxr-xr-x[-rw-r--r--]OpenSim/Framework/Monitoring/Stats/EventHistogram.cs346
-rw-r--r--OpenSim/Framework/Monitoring/Stats/Stat.cs51
-rw-r--r--OpenSim/Framework/Monitoring/StatsLogger.cs6
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs106
5 files changed, 264 insertions, 245 deletions
diff --git a/OpenSim/Framework/Monitoring/Stats/CounterStat.cs b/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
index 318cf1c..318cf1c 100644..100755
--- a/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
diff --git a/OpenSim/Framework/Monitoring/Stats/EventHistogram.cs b/OpenSim/Framework/Monitoring/Stats/EventHistogram.cs
index f51f322..bc56372 100644..100755
--- a/OpenSim/Framework/Monitoring/Stats/EventHistogram.cs
+++ b/OpenSim/Framework/Monitoring/Stats/EventHistogram.cs
@@ -1,173 +1,173 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 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 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 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq; 30using System.Linq;
31using System.Text; 31using System.Text;
32 32
33using OpenMetaverse.StructuredData; 33using OpenMetaverse.StructuredData;
34 34
35namespace OpenSim.Framework.Monitoring 35namespace OpenSim.Framework.Monitoring
36{ 36{
37// Create a time histogram of events. The histogram is built in a wrap-around 37// Create a time histogram of events. The histogram is built in a wrap-around
38// array of equally distributed buckets. 38// array of equally distributed buckets.
39// For instance, a minute long histogram of second sized buckets would be: 39// For instance, a minute long histogram of second sized buckets would be:
40// new EventHistogram(60, 1000) 40// new EventHistogram(60, 1000)
41public class EventHistogram 41public class EventHistogram
42{ 42{
43 private int m_timeBase; 43 private int m_timeBase;
44 private int m_numBuckets; 44 private int m_numBuckets;
45 private int m_bucketMilliseconds; 45 private int m_bucketMilliseconds;
46 private int m_lastBucket; 46 private int m_lastBucket;
47 private int m_totalHistogramMilliseconds; 47 private int m_totalHistogramMilliseconds;
48 private long[] m_histogram; 48 private long[] m_histogram;
49 private object histoLock = new object(); 49 private object histoLock = new object();
50 50
51 public EventHistogram(int numberOfBuckets, int millisecondsPerBucket) 51 public EventHistogram(int numberOfBuckets, int millisecondsPerBucket)
52 { 52 {
53 m_numBuckets = numberOfBuckets; 53 m_numBuckets = numberOfBuckets;
54 m_bucketMilliseconds = millisecondsPerBucket; 54 m_bucketMilliseconds = millisecondsPerBucket;
55 m_totalHistogramMilliseconds = m_numBuckets * m_bucketMilliseconds; 55 m_totalHistogramMilliseconds = m_numBuckets * m_bucketMilliseconds;
56 56
57 m_histogram = new long[m_numBuckets]; 57 m_histogram = new long[m_numBuckets];
58 Zero(); 58 Zero();
59 m_lastBucket = 0; 59 m_lastBucket = 0;
60 m_timeBase = Util.EnvironmentTickCount(); 60 m_timeBase = Util.EnvironmentTickCount();
61 } 61 }
62 62
63 public void Event() 63 public void Event()
64 { 64 {
65 this.Event(1); 65 this.Event(1);
66 } 66 }
67 67
68 // Record an event at time 'now' in the histogram. 68 // Record an event at time 'now' in the histogram.
69 public void Event(int cnt) 69 public void Event(int cnt)
70 { 70 {
71 lock (histoLock) 71 lock (histoLock)
72 { 72 {
73 // The time as displaced from the base of the histogram 73 // The time as displaced from the base of the histogram
74 int bucketTime = Util.EnvironmentTickCountSubtract(m_timeBase); 74 int bucketTime = Util.EnvironmentTickCountSubtract(m_timeBase);
75 75
76 // If more than the total time of the histogram, we just start over 76 // If more than the total time of the histogram, we just start over
77 if (bucketTime > m_totalHistogramMilliseconds) 77 if (bucketTime > m_totalHistogramMilliseconds)
78 { 78 {
79 Zero(); 79 Zero();
80 m_lastBucket = 0; 80 m_lastBucket = 0;
81 m_timeBase = Util.EnvironmentTickCount(); 81 m_timeBase = Util.EnvironmentTickCount();
82 } 82 }
83 else 83 else
84 { 84 {
85 // To which bucket should we add this event? 85 // To which bucket should we add this event?
86 int bucket = bucketTime / m_bucketMilliseconds; 86 int bucket = bucketTime / m_bucketMilliseconds;
87 87
88 // Advance m_lastBucket to the new bucket. Zero any buckets skipped over. 88 // Advance m_lastBucket to the new bucket. Zero any buckets skipped over.
89 while (bucket != m_lastBucket) 89 while (bucket != m_lastBucket)
90 { 90 {
91 // Zero from just after the last bucket to the new bucket or the end 91 // Zero from just after the last bucket to the new bucket or the end
92 for (int jj = m_lastBucket + 1; jj <= Math.Min(bucket, m_numBuckets - 1); jj++) 92 for (int jj = m_lastBucket + 1; jj <= Math.Min(bucket, m_numBuckets - 1); jj++)
93 { 93 {
94 m_histogram[jj] = 0; 94 m_histogram[jj] = 0;
95 } 95 }
96 m_lastBucket = bucket; 96 m_lastBucket = bucket;
97 // If the new bucket is off the end, wrap around to the beginning 97 // If the new bucket is off the end, wrap around to the beginning
98 if (bucket > m_numBuckets) 98 if (bucket > m_numBuckets)
99 { 99 {
100 bucket -= m_numBuckets; 100 bucket -= m_numBuckets;
101 m_lastBucket = 0; 101 m_lastBucket = 0;
102 m_histogram[m_lastBucket] = 0; 102 m_histogram[m_lastBucket] = 0;
103 m_timeBase += m_totalHistogramMilliseconds; 103 m_timeBase += m_totalHistogramMilliseconds;
104 } 104 }
105 } 105 }
106 } 106 }
107 m_histogram[m_lastBucket] += cnt; 107 m_histogram[m_lastBucket] += cnt;
108 } 108 }
109 } 109 }
110 110
111 // Get a copy of the current histogram 111 // Get a copy of the current histogram
112 public long[] GetHistogram() 112 public long[] GetHistogram()
113 { 113 {
114 long[] ret = new long[m_numBuckets]; 114 long[] ret = new long[m_numBuckets];
115 lock (histoLock) 115 lock (histoLock)
116 { 116 {
117 int indx = m_lastBucket + 1; 117 int indx = m_lastBucket + 1;
118 for (int ii = 0; ii < m_numBuckets; ii++, indx++) 118 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
119 { 119 {
120 if (indx >= m_numBuckets) 120 if (indx >= m_numBuckets)
121 indx = 0; 121 indx = 0;
122 ret[ii] = m_histogram[indx]; 122 ret[ii] = m_histogram[indx];
123 } 123 }
124 } 124 }
125 return ret; 125 return ret;
126 } 126 }
127 127
128 public OSDMap GetHistogramAsOSDMap() 128 public OSDMap GetHistogramAsOSDMap()
129 { 129 {
130 OSDMap ret = new OSDMap(); 130 OSDMap ret = new OSDMap();
131 131
132 ret.Add("Buckets", OSD.FromInteger(m_numBuckets)); 132 ret.Add("Buckets", OSD.FromInteger(m_numBuckets));
133 ret.Add("BucketMilliseconds", OSD.FromInteger(m_bucketMilliseconds)); 133 ret.Add("BucketMilliseconds", OSD.FromInteger(m_bucketMilliseconds));
134 ret.Add("TotalMilliseconds", OSD.FromInteger(m_totalHistogramMilliseconds)); 134 ret.Add("TotalMilliseconds", OSD.FromInteger(m_totalHistogramMilliseconds));
135 135
136 // Compute a number for the first bucket in the histogram. 136 // Compute a number for the first bucket in the histogram.
137 // This will allow readers to know how this histogram relates to any previously read histogram. 137 // This will allow readers to know how this histogram relates to any previously read histogram.
138 int baseBucketNum = (m_timeBase / m_bucketMilliseconds) + m_lastBucket + 1; 138 int baseBucketNum = (m_timeBase / m_bucketMilliseconds) + m_lastBucket + 1;
139 ret.Add("BaseNumber", OSD.FromInteger(baseBucketNum)); 139 ret.Add("BaseNumber", OSD.FromInteger(baseBucketNum));
140 140
141 ret.Add("Values", GetHistogramAsOSDArray()); 141 ret.Add("Values", GetHistogramAsOSDArray());
142 142
143 return ret; 143 return ret;
144 } 144 }
145 // Get a copy of the current histogram 145 // Get a copy of the current histogram
146 public OSDArray GetHistogramAsOSDArray() 146 public OSDArray GetHistogramAsOSDArray()
147 { 147 {
148 OSDArray ret = new OSDArray(m_numBuckets); 148 OSDArray ret = new OSDArray(m_numBuckets);
149 lock (histoLock) 149 lock (histoLock)
150 { 150 {
151 int indx = m_lastBucket + 1; 151 int indx = m_lastBucket + 1;
152 for (int ii = 0; ii < m_numBuckets; ii++, indx++) 152 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
153 { 153 {
154 if (indx >= m_numBuckets) 154 if (indx >= m_numBuckets)
155 indx = 0; 155 indx = 0;
156 ret[ii] = OSD.FromLong(m_histogram[indx]); 156 ret[ii] = OSD.FromLong(m_histogram[indx]);
157 } 157 }
158 } 158 }
159 return ret; 159 return ret;
160 } 160 }
161 161
162 // Zero out the histogram 162 // Zero out the histogram
163 public void Zero() 163 public void Zero()
164 { 164 {
165 lock (histoLock) 165 lock (histoLock)
166 { 166 {
167 for (int ii = 0; ii < m_numBuckets; ii++) 167 for (int ii = 0; ii < m_numBuckets; ii++)
168 m_histogram[ii] = 0; 168 m_histogram[ii] = 0;
169 } 169 }
170 } 170 }
171} 171}
172 172
173} 173}
diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs
index a7cb2a6..2402acd 100644
--- a/OpenSim/Framework/Monitoring/Stats/Stat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs
@@ -121,17 +121,17 @@ namespace OpenSim.Framework.Monitoring
121 string container, 121 string container,
122 StatType type, 122 StatType type,
123 Action<Stat> pullAction, 123 Action<Stat> pullAction,
124 StatVerbosity verbosity) 124 StatVerbosity verbosity)
125 : this( 125 : this(
126 shortName, 126 shortName,
127 name, 127 name,
128 description, 128 description,
129 unitName, 129 unitName,
130 category, 130 category,
131 container, 131 container,
132 type, 132 type,
133 MeasuresOfInterest.None, 133 MeasuresOfInterest.None,
134 pullAction, 134 pullAction,
135 verbosity) 135 verbosity)
136 { 136 {
137 } 137 }
@@ -227,11 +227,11 @@ namespace OpenSim.Framework.Monitoring
227 { 227 {
228 StringBuilder sb = new StringBuilder(); 228 StringBuilder sb = new StringBuilder();
229 sb.AppendFormat( 229 sb.AppendFormat(
230 "{0}.{1}.{2} : {3}{4}", 230 "{0}.{1}.{2} : {3}{4}",
231 Category, 231 Category,
232 Container, 232 Container,
233 ShortName, 233 ShortName,
234 Value, 234 Value,
235 string.IsNullOrEmpty(UnitName) ? "" : string.Format(" {0}", UnitName)); 235 string.IsNullOrEmpty(UnitName) ? "" : string.Format(" {0}", UnitName));
236 236
237 AppendMeasuresOfInterest(sb); 237 AppendMeasuresOfInterest(sb);
@@ -239,6 +239,17 @@ namespace OpenSim.Framework.Monitoring
239 return sb.ToString(); 239 return sb.ToString();
240 } 240 }
241 241
242 public virtual OSDMap ToBriefOSDMap()
243 {
244 OSDMap ret = new OSDMap();
245
246 ret.Add("Value", OSD.FromReal(Value));
247
248 double lastChangeOverTime, averageChangeOverTime;
249
250 return ret;
251 }
252
242 public virtual OSDMap ToOSDMap() 253 public virtual OSDMap ToOSDMap()
243 { 254 {
244 OSDMap ret = new OSDMap(); 255 OSDMap ret = new OSDMap();
@@ -279,7 +290,7 @@ namespace OpenSim.Framework.Monitoring
279 lock (m_samples) 290 lock (m_samples)
280 { 291 {
281 // m_log.DebugFormat( 292 // m_log.DebugFormat(
282 // "[STAT]: Samples for {0} are {1}", 293 // "[STAT]: Samples for {0} are {1}",
283 // Name, string.Join(",", m_samples.Select(s => s.ToString()).ToArray())); 294 // Name, string.Join(",", m_samples.Select(s => s.ToString()).ToArray()));
284 295
285 foreach (double s in m_samples) 296 foreach (double s in m_samples)
@@ -315,12 +326,12 @@ namespace OpenSim.Framework.Monitoring
315 if (ComputeMeasuresOfInterest(out lastChangeOverTime, out averageChangeOverTime)) 326 if (ComputeMeasuresOfInterest(out lastChangeOverTime, out averageChangeOverTime))
316 { 327 {
317 sb.AppendFormat( 328 sb.AppendFormat(
318 ", {0:0.##}{1}/s, {2:0.##}{3}/s", 329 ", {0:0.##}{1}/s, {2:0.##}{3}/s",
319 lastChangeOverTime, 330 lastChangeOverTime,
320 string.IsNullOrEmpty(UnitName) ? "" : string.Format(" {0}", UnitName), 331 string.IsNullOrEmpty(UnitName) ? "" : string.Format(" {0}", UnitName),
321 averageChangeOverTime, 332 averageChangeOverTime,
322 string.IsNullOrEmpty(UnitName) ? "" : string.Format(" {0}", UnitName)); 333 string.IsNullOrEmpty(UnitName) ? "" : string.Format(" {0}", UnitName));
323 } 334 }
324 } 335 }
325 } 336 }
326} \ No newline at end of file 337}
diff --git a/OpenSim/Framework/Monitoring/StatsLogger.cs b/OpenSim/Framework/Monitoring/StatsLogger.cs
index 15a37aa..b719af9 100644
--- a/OpenSim/Framework/Monitoring/StatsLogger.cs
+++ b/OpenSim/Framework/Monitoring/StatsLogger.cs
@@ -99,13 +99,13 @@ namespace OpenSim.Framework.Monitoring
99 } 99 }
100 100
101 string path = cmd[2]; 101 string path = cmd[2];
102 102
103 using (StreamWriter sw = new StreamWriter(path, true)) 103 using (StreamWriter sw = new StreamWriter(path, true))
104 { 104 {
105 foreach (string line in GetReport()) 105 foreach (string line in GetReport())
106 sw.WriteLine(line); 106 sw.WriteLine(line);
107 } 107 }
108 108
109 MainConsole.Instance.OutputFormat("Stats saved to file {0}", path); 109 MainConsole.Instance.OutputFormat("Stats saved to file {0}", path);
110 } 110 }
111 111
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index 3136ee8..a6b341f 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -47,6 +47,8 @@ namespace OpenSim.Framework.Monitoring
47 // Subcommand used to list other stats. 47 // Subcommand used to list other stats.
48 public const string ListSubCommand = "list"; 48 public const string ListSubCommand = "list";
49 49
50 public static string StatsPassword { get; set; }
51
50 // All subcommands 52 // All subcommands
51 public static HashSet<string> SubCommands = new HashSet<string> { AllSubCommand, ListSubCommand }; 53 public static HashSet<string> SubCommands = new HashSet<string> { AllSubCommand, ListSubCommand };
52 54
@@ -80,8 +82,7 @@ namespace OpenSim.Framework.Monitoring
80 + "'all' will show all statistics.\n" 82 + "'all' will show all statistics.\n"
81 + "A <category> name will show statistics from that category.\n" 83 + "A <category> name will show statistics from that category.\n"
82 + "A <category>.<container> name will show statistics from that category in that container.\n" 84 + "A <category>.<container> name will show statistics from that category in that container.\n"
83 + "More than one name can be given separated by spaces.\n" 85 + "More than one name can be given separated by spaces.\n",
84 + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
85 HandleShowStatsCommand); 86 HandleShowStatsCommand);
86 87
87 console.Commands.AddCommand( 88 console.Commands.AddCommand(
@@ -91,7 +92,6 @@ namespace OpenSim.Framework.Monitoring
91 "show stats [list|all|(<category>[.<container>])+", 92 "show stats [list|all|(<category>[.<container>])+",
92 "Alias for 'stats show' command", 93 "Alias for 'stats show' command",
93 HandleShowStatsCommand); 94 HandleShowStatsCommand);
94
95 StatsLogger.RegisterConsoleCommands(console); 95 StatsLogger.RegisterConsoleCommands(console);
96 } 96 }
97 97
@@ -262,33 +262,36 @@ namespace OpenSim.Framework.Monitoring
262 { 262 {
263 OSDMap map = new OSDMap(); 263 OSDMap map = new OSDMap();
264 264
265 foreach (string catName in RegisteredStats.Keys) 265 lock (RegisteredStats)
266 { 266 {
267 // Do this category if null spec, "all" subcommand or category name matches passed parameter. 267 foreach (string catName in RegisteredStats.Keys)
268 // Skip category if none of the above.
269 if (!(String.IsNullOrEmpty(pCategoryName) || pCategoryName == AllSubCommand || pCategoryName == catName))
270 continue;
271
272 OSDMap contMap = new OSDMap();
273 foreach (string contName in RegisteredStats[catName].Keys)
274 { 268 {
275 if (!(string.IsNullOrEmpty(pContainerName) || pContainerName == AllSubCommand || pContainerName == contName)) 269 // Do this category if null spec, "all" subcommand or category name matches passed parameter.
270 // Skip category if none of the above.
271 if (!(String.IsNullOrEmpty(pCategoryName) || pCategoryName == AllSubCommand || pCategoryName == catName))
276 continue; 272 continue;
277
278 OSDMap statMap = new OSDMap();
279 273
280 SortedDictionary<string, Stat> theStats = RegisteredStats[catName][contName]; 274 OSDMap contMap = new OSDMap();
281 foreach (string statName in theStats.Keys) 275 foreach (string contName in RegisteredStats[catName].Keys)
282 { 276 {
283 if (!(String.IsNullOrEmpty(pStatName) || pStatName == AllSubCommand || pStatName == statName)) 277 if (!(string.IsNullOrEmpty(pContainerName) || pContainerName == AllSubCommand || pContainerName == contName))
284 continue; 278 continue;
285 279
286 statMap.Add(statName, theStats[statName].ToOSDMap()); 280 OSDMap statMap = new OSDMap();
287 } 281
282 SortedDictionary<string, Stat> theStats = RegisteredStats[catName][contName];
283 foreach (string statName in theStats.Keys)
284 {
285 if (!(String.IsNullOrEmpty(pStatName) || pStatName == AllSubCommand || pStatName == statName))
286 continue;
287
288 statMap.Add(statName, theStats[statName].ToBriefOSDMap());
289 }
288 290
289 contMap.Add(contName, statMap); 291 contMap.Add(contName, statMap);
292 }
293 map.Add(catName, contMap);
290 } 294 }
291 map.Add(catName, contMap);
292 } 295 }
293 296
294 return map; 297 return map;
@@ -301,6 +304,17 @@ namespace OpenSim.Framework.Monitoring
301 int response_code = 200; 304 int response_code = 200;
302 string contenttype = "text/json"; 305 string contenttype = "text/json";
303 306
307 if (StatsPassword != String.Empty && (!request.ContainsKey("pass") || request["pass"].ToString() != StatsPassword))
308 {
309 responsedata["int_response_code"] = response_code;
310 responsedata["content_type"] = "text/plain";
311 responsedata["keepalive"] = false;
312 responsedata["str_response_string"] = "Access denied";
313 responsedata["access_control_allow_origin"] = "*";
314
315 return responsedata;
316 }
317
304 string pCategoryName = StatsManager.AllSubCommand; 318 string pCategoryName = StatsManager.AllSubCommand;
305 string pContainerName = StatsManager.AllSubCommand; 319 string pContainerName = StatsManager.AllSubCommand;
306 string pStatName = StatsManager.AllSubCommand; 320 string pStatName = StatsManager.AllSubCommand;
@@ -358,8 +372,8 @@ namespace OpenSim.Framework.Monitoring
358 /// <returns></returns> 372 /// <returns></returns>
359 public static bool RegisterStat(Stat stat) 373 public static bool RegisterStat(Stat stat)
360 { 374 {
361 SortedDictionary<string, SortedDictionary<string, Stat>> category = null, newCategory; 375 SortedDictionary<string, SortedDictionary<string, Stat>> category = null;
362 SortedDictionary<string, Stat> container = null, newContainer; 376 SortedDictionary<string, Stat> container = null;
363 377
364 lock (RegisteredStats) 378 lock (RegisteredStats)
365 { 379 {
@@ -369,22 +383,15 @@ namespace OpenSim.Framework.Monitoring
369 if (TryGetStatParents(stat, out category, out container)) 383 if (TryGetStatParents(stat, out category, out container))
370 return false; 384 return false;
371 385
372 // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed. 386 if (container == null)
373 // This means that we don't need to lock or copy them on iteration, which will be a much more 387 container = new SortedDictionary<string, Stat>();
374 // common operation after startup.
375 if (container != null)
376 newContainer = new SortedDictionary<string, Stat>(container);
377 else
378 newContainer = new SortedDictionary<string, Stat>();
379 388
380 if (category != null) 389 if (category == null)
381 newCategory = new SortedDictionary<string, SortedDictionary<string, Stat>>(category); 390 category = new SortedDictionary<string, SortedDictionary<string, Stat>>();
382 else
383 newCategory = new SortedDictionary<string, SortedDictionary<string, Stat>>();
384 391
385 newContainer[stat.ShortName] = stat; 392 container[stat.ShortName] = stat;
386 newCategory[stat.Container] = newContainer; 393 category[stat.Container] = container;
387 RegisteredStats[stat.Category] = newCategory; 394 RegisteredStats[stat.Category] = category;
388 } 395 }
389 396
390 return true; 397 return true;
@@ -397,23 +404,24 @@ namespace OpenSim.Framework.Monitoring
397 /// <returns></returns> 404 /// <returns></returns>
398 public static bool DeregisterStat(Stat stat) 405 public static bool DeregisterStat(Stat stat)
399 { 406 {
400 SortedDictionary<string, SortedDictionary<string, Stat>> category = null, newCategory; 407 SortedDictionary<string, SortedDictionary<string, Stat>> category = null;
401 SortedDictionary<string, Stat> container = null, newContainer; 408 SortedDictionary<string, Stat> container = null;
402 409
403 lock (RegisteredStats) 410 lock (RegisteredStats)
404 { 411 {
405 if (!TryGetStatParents(stat, out category, out container)) 412 if (!TryGetStatParents(stat, out category, out container))
406 return false; 413 return false;
407 414
408 newContainer = new SortedDictionary<string, Stat>(container); 415 if(container != null)
409 newContainer.Remove(stat.ShortName); 416 {
410 417 container.Remove(stat.ShortName);
411 newCategory = new SortedDictionary<string, SortedDictionary<string, Stat>>(category); 418 if(category != null && container.Count == 0)
412 newCategory.Remove(stat.Container); 419 {
413 420 category.Remove(stat.Container);
414 newCategory[stat.Container] = newContainer; 421 if(category.Count == 0)
415 RegisteredStats[stat.Category] = newCategory; 422 RegisteredStats.Remove(stat.Category);
416 423 }
424 }
417 return true; 425 return true;
418 } 426 }
419 } 427 }
@@ -554,4 +562,4 @@ namespace OpenSim.Framework.Monitoring
554 Debug, 562 Debug,
555 Info 563 Info
556 } 564 }
557} \ No newline at end of file 565}