aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorMelanie2013-02-26 13:34:20 +0000
committerMelanie2013-02-26 13:34:20 +0000
commit54ee95dd8e6649723d92ac893e1699d34822cd80 (patch)
treed1d15e17c0a04bef247bfe8e6e0cffd3f8460ff1 /OpenSim
parentMake sure state machine is reset if crossing is aborted (diff)
parentBulletSim: tweeks to make avatar jump work better. (diff)
downloadopensim-SC_OLD-54ee95dd8e6649723d92ac893e1699d34822cd80.zip
opensim-SC_OLD-54ee95dd8e6649723d92ac893e1699d34822cd80.tar.gz
opensim-SC_OLD-54ee95dd8e6649723d92ac893e1699d34822cd80.tar.bz2
opensim-SC_OLD-54ee95dd8e6649723d92ac893e1699d34822cd80.tar.xz
Merge branch 'master' into careminster
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs9
-rw-r--r--OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs2
-rw-r--r--OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs9
-rw-r--r--OpenSim/Addons/Groups/Service/GroupsService.cs6
-rwxr-xr-xOpenSim/Framework/Monitoring/Stats/CounterStat.cs439
-rw-r--r--OpenSim/Framework/Monitoring/Stats/Stat.cs2
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs29
-rw-r--r--OpenSim/Framework/Util.cs27
-rw-r--r--OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs48
-rw-r--r--OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs24
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs20
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs9
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs11
-rw-r--r--OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs328
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs10
16 files changed, 708 insertions, 269 deletions
diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs
index d1c02db..f1cf66c 100644
--- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs
+++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs
@@ -74,11 +74,8 @@ namespace OpenSim.Groups
74 { 74 {
75 IConfig groupsConfig = config.Configs["Groups"]; 75 IConfig groupsConfig = config.Configs["Groups"];
76 string url = groupsConfig.GetString("GroupsServerURI", string.Empty); 76 string url = groupsConfig.GetString("GroupsServerURI", string.Empty);
77 if (url == string.Empty) 77 if (!Uri.IsWellFormedUriString(url, UriKind.Absolute))
78 { 78 throw new Exception(string.Format("[Groups.RemoteConnector]: Malformed groups server URL {0}. Fix it or disable the Groups feature.", url));
79 m_log.WarnFormat("[Groups.RemoteConnector]: Groups server URL not provided. Groups will not work.");
80 return;
81 }
82 79
83 m_GroupsService = new GroupsServiceRemoteConnector(url); 80 m_GroupsService = new GroupsServiceRemoteConnector(url);
84 m_Scenes = new List<Scene>(); 81 m_Scenes = new List<Scene>();
@@ -273,7 +270,7 @@ namespace OpenSim.Groups
273 public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason) 270 public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason)
274 { 271 {
275 string r = string.Empty; 272 string r = string.Empty;
276 bool success = m_CacheWrapper.AddGroupRole(roleID, description, name, powers, title, delegate 273 bool success = m_CacheWrapper.AddGroupRole(groupID, roleID, description, name, powers, title, delegate
277 { 274 {
278 return m_GroupsService.AddGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, out r); 275 return m_GroupsService.AddGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, out r);
279 }); 276 });
diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs
index 8c257ed..f991d01 100644
--- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs
+++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs
@@ -371,7 +371,7 @@ namespace OpenSim.Groups
371 Dictionary<string, object> result = new Dictionary<string, object>(); 371 Dictionary<string, object> result = new Dictionary<string, object>();
372 372
373 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID") || 373 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID") ||
374 !request.ContainsKey("Name") || !request.ContainsKey("Descrption") || !request.ContainsKey("Title") || 374 !request.ContainsKey("Name") || !request.ContainsKey("Description") || !request.ContainsKey("Title") ||
375 !request.ContainsKey("Powers") || !request.ContainsKey("OP")) 375 !request.ContainsKey("Powers") || !request.ContainsKey("OP"))
376 NullResult(result, "Bad network data"); 376 NullResult(result, "Bad network data");
377 377
diff --git a/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs b/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs
index f789626..e7d38c2 100644
--- a/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs
+++ b/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs
@@ -393,7 +393,7 @@ namespace OpenSim.Groups
393 } 393 }
394 } 394 }
395 395
396 public bool AddGroupRole(UUID roleID, string description, string name, ulong powers, string title, BooleanDelegate d) 396 public bool AddGroupRole(UUID groupID, UUID roleID, string description, string name, ulong powers, string title, BooleanDelegate d)
397 { 397 {
398 if (d()) 398 if (d())
399 { 399 {
@@ -406,8 +406,15 @@ namespace OpenSim.Groups
406 role.Title = title; 406 role.Title = title;
407 407
408 lock (m_Cache) 408 lock (m_Cache)
409 {
409 m_Cache.AddOrUpdate("role-" + roleID.ToString(), role, GROUPS_CACHE_TIMEOUT); 410 m_Cache.AddOrUpdate("role-" + roleID.ToString(), role, GROUPS_CACHE_TIMEOUT);
410 411
412 // also remove this list
413 if (m_Cache.Contains("roles-" + groupID.ToString()))
414 m_Cache.Remove("roles-" + groupID.ToString());
415
416 }
417
411 return true; 418 return true;
412 } 419 }
413 420
diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs
index fc567dd..0668870 100644
--- a/OpenSim/Addons/Groups/Service/GroupsService.cs
+++ b/OpenSim/Addons/Groups/Service/GroupsService.cs
@@ -785,10 +785,16 @@ namespace OpenSim.Groups
785 RoleData data = m_Database.RetrieveRole(groupID, roleID); 785 RoleData data = m_Database.RetrieveRole(groupID, roleID);
786 786
787 if (add && data != null) // it already exists, can't create 787 if (add && data != null) // it already exists, can't create
788 {
789 m_log.DebugFormat("[Groups]: Group {0} already exists. Can't create it again", groupID);
788 return false; 790 return false;
791 }
789 792
790 if (!add && data == null) // it deosn't exist, can't update 793 if (!add && data == null) // it deosn't exist, can't update
794 {
795 m_log.DebugFormat("[Groups]: Group {0} doesn't exist. Can't update it", groupID);
791 return false; 796 return false;
797 }
792 798
793 if (add) 799 if (add)
794 data = new RoleData(); 800 data = new RoleData();
diff --git a/OpenSim/Framework/Monitoring/Stats/CounterStat.cs b/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
index d81f182..caea30d 100755
--- a/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
@@ -1,211 +1,228 @@
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 // Get a copy of the current histogram 128 public OSDMap GetHistogramAsOSDMap()
129 public OSDArray GetHistogramAsOSDArray() 129 {
130 { 130 OSDMap ret = new OSDMap();
131 OSDArray ret = new OSDArray(m_numBuckets); 131
132 lock (histoLock) 132 ret.Add("Buckets", OSD.FromInteger(m_numBuckets));
133 { 133 ret.Add("BucketMilliseconds", OSD.FromInteger(m_bucketMilliseconds));
134 int indx = m_lastBucket + 1; 134 ret.Add("TotalMilliseconds", OSD.FromInteger(m_totalHistogramMilliseconds));
135 for (int ii = 0; ii < m_numBuckets; ii++, indx++) 135
136 { 136 // Compute a number for the first bucket in the histogram.
137 if (indx >= m_numBuckets) 137 // This will allow readers to know how this histogram relates to any previously read histogram.
138 indx = 0; 138 int baseBucketNum = (m_timeBase / m_bucketMilliseconds) + m_lastBucket + 1;
139 ret[ii] = OSD.FromLong(m_histogram[indx]); 139 ret.Add("BaseNumber", OSD.FromInteger(baseBucketNum));
140 } 140
141 } 141 ret.Add("Values", GetHistogramAsOSDArray());
142 return ret; 142
143 } 143 return ret;
144 144 }
145 // Zero out the histogram 145 // Get a copy of the current histogram
146 public void Zero() 146 public OSDArray GetHistogramAsOSDArray()
147 { 147 {
148 lock (histoLock) 148 OSDArray ret = new OSDArray(m_numBuckets);
149 { 149 lock (histoLock)
150 for (int ii = 0; ii < m_numBuckets; ii++) 150 {
151 m_histogram[ii] = 0; 151 int indx = m_lastBucket + 1;
152 } 152 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
153 } 153 {
154} 154 if (indx >= m_numBuckets)
155 155 indx = 0;
156// A statistic that wraps a counter. 156 ret[ii] = OSD.FromLong(m_histogram[indx]);
157// Built this way mostly so histograms and history can be created. 157 }
158public class CounterStat : Stat 158 }
159{ 159 return ret;
160 private SortedDictionary<string, EventHistogram> m_histograms; 160 }
161 private object counterLock = new object(); 161
162 162 // Zero out the histogram
163 public CounterStat( 163 public void Zero()
164 string shortName, 164 {
165 string name, 165 lock (histoLock)
166 string description, 166 {
167 string unitName, 167 for (int ii = 0; ii < m_numBuckets; ii++)
168 string category, 168 m_histogram[ii] = 0;
169 string container, 169 }
170 StatVerbosity verbosity) 170 }
171 : base(shortName, name, description, unitName, category, container, StatType.Push, null, verbosity) 171}
172 { 172
173 m_histograms = new SortedDictionary<string, EventHistogram>(); 173// A statistic that wraps a counter.
174 } 174// Built this way mostly so histograms and history can be created.
175 175public class CounterStat : Stat
176 // Histograms are presumably added at intialization time and the list does not change thereafter. 176{
177 // Thus no locking of the histogram list. 177 private SortedDictionary<string, EventHistogram> m_histograms;
178 public void AddHistogram(string histoName, EventHistogram histo) 178 private object counterLock = new object();
179 { 179
180 m_histograms.Add(histoName, histo); 180 public CounterStat(
181 } 181 string shortName,
182 182 string name,
183 public delegate void ProcessHistogram(string name, EventHistogram histo); 183 string description,
184 public void ForEachHistogram(ProcessHistogram process) 184 string unitName,
185 { 185 string category,
186 foreach (KeyValuePair<string, EventHistogram> kvp in m_histograms) 186 string container,
187 { 187 StatVerbosity verbosity)
188 process(kvp.Key, kvp.Value); 188 : base(shortName, name, description, unitName, category, container, StatType.Push, null, verbosity)
189 } 189 {
190 } 190 m_histograms = new SortedDictionary<string, EventHistogram>();
191 191 }
192 public void Event() 192
193 { 193 // Histograms are presumably added at intialization time and the list does not change thereafter.
194 this.Event(1); 194 // Thus no locking of the histogram list.
195 } 195 public void AddHistogram(string histoName, EventHistogram histo)
196 196 {
197 // Count the underlying counter. 197 m_histograms.Add(histoName, histo);
198 public void Event(int cnt) 198 }
199 { 199
200 lock (counterLock) 200 public delegate void ProcessHistogram(string name, EventHistogram histo);
201 { 201 public void ForEachHistogram(ProcessHistogram process)
202 base.Value += cnt; 202 {
203 203 foreach (KeyValuePair<string, EventHistogram> kvp in m_histograms)
204 foreach (EventHistogram histo in m_histograms.Values) 204 {
205 { 205 process(kvp.Key, kvp.Value);
206 histo.Event(cnt); 206 }
207 } 207 }
208 } 208
209 } 209 public void Event()
210} 210 {
211} 211 this.Event(1);
212 }
213
214 // Count the underlying counter.
215 public void Event(int cnt)
216 {
217 lock (counterLock)
218 {
219 base.Value += cnt;
220
221 foreach (EventHistogram histo in m_histograms.Values)
222 {
223 histo.Event(cnt);
224 }
225 }
226 }
227}
228}
diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs
index c8d9174..2e7665f 100644
--- a/OpenSim/Framework/Monitoring/Stats/Stat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs
@@ -211,7 +211,7 @@ namespace OpenSim.Framework.Monitoring
211 public virtual string ToConsoleString() 211 public virtual string ToConsoleString()
212 { 212 {
213 StringBuilder sb = new StringBuilder(); 213 StringBuilder sb = new StringBuilder();
214 sb.AppendFormat("{0}.{1}.{2} : {3}{4}", Category, Container, ShortName, Value, UnitName); 214 sb.AppendFormat("{0}.{1}.{2} : {3} {4}", Category, Container, ShortName, Value, UnitName);
215 215
216 AppendMeasuresOfInterest(sb); 216 AppendMeasuresOfInterest(sb);
217 217
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index 910907e..24db6d4 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -85,6 +85,7 @@ namespace OpenSim.Framework.Monitoring
85 if (cmd.Length > 2) 85 if (cmd.Length > 2)
86 { 86 {
87 var categoryName = cmd[2]; 87 var categoryName = cmd[2];
88 var containerName = cmd.Length > 3 ? cmd[3] : String.Empty;
88 89
89 if (categoryName == AllSubCommand) 90 if (categoryName == AllSubCommand)
90 { 91 {
@@ -108,7 +109,20 @@ namespace OpenSim.Framework.Monitoring
108 } 109 }
109 else 110 else
110 { 111 {
111 OutputCategoryStatsToConsole(con, category); 112 if (String.IsNullOrEmpty(containerName))
113 OutputCategoryStatsToConsole(con, category);
114 else
115 {
116 SortedDictionary<string, Stat> container;
117 if (category.TryGetValue(containerName, out container))
118 {
119 OutputContainerStatsToConsole(con, container);
120 }
121 else
122 {
123 con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
124 }
125 }
112 } 126 }
113 } 127 }
114 } 128 }
@@ -124,10 +138,15 @@ namespace OpenSim.Framework.Monitoring
124 { 138 {
125 foreach (var container in category.Values) 139 foreach (var container in category.Values)
126 { 140 {
127 foreach (Stat stat in container.Values) 141 OutputContainerStatsToConsole(con, container);
128 { 142 }
129 con.Output(stat.ToConsoleString()); 143 }
130 } 144
145 private static void OutputContainerStatsToConsole( ICommandConsole con, SortedDictionary<string, Stat> container)
146 {
147 foreach (Stat stat in container.Values)
148 {
149 con.Output(stat.ToConsoleString());
131 } 150 }
132 } 151 }
133 152
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index aadcdc8..96644ec 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -929,7 +929,25 @@ namespace OpenSim.Framework
929 /// <returns></returns> 929 /// <returns></returns>
930 public static T GetConfigVarFromSections<T>(IConfigSource config, string varname, string[] sections) 930 public static T GetConfigVarFromSections<T>(IConfigSource config, string varname, string[] sections)
931 { 931 {
932 object val = default(T); 932 return GetConfigVarFromSections<T>(config, varname, sections, default(T));
933 }
934
935 /// <summary>
936 /// Gets the value of a configuration variable by looking into
937 /// multiple sections in order. The latter sections overwrite
938 /// any values previously found.
939 /// </summary>
940 /// <remarks>
941 /// If no value is found then the given default value is returned
942 /// </remarks>
943 /// <typeparam name="T">Type of the variable</typeparam>
944 /// <param name="config">The configuration object</param>
945 /// <param name="varname">The configuration variable</param>
946 /// <param name="sections">Ordered sequence of sections to look at</param>
947 /// <param name="val">Default value</param>
948 /// <returns></returns>
949 public static T GetConfigVarFromSections<T>(IConfigSource config, string varname, string[] sections, object val)
950 {
933 foreach (string section in sections) 951 foreach (string section in sections)
934 { 952 {
935 IConfig cnf = config.Configs[section]; 953 IConfig cnf = config.Configs[section];
@@ -937,11 +955,7 @@ namespace OpenSim.Framework
937 continue; 955 continue;
938 956
939 if (typeof(T) == typeof(String)) 957 if (typeof(T) == typeof(String))
940 {
941 if (val == null) // no null strings, please
942 val = string.Empty;
943 val = cnf.GetString(varname, (string)val); 958 val = cnf.GetString(varname, (string)val);
944 }
945 else if (typeof(T) == typeof(Boolean)) 959 else if (typeof(T) == typeof(Boolean))
946 val = cnf.GetBoolean(varname, (bool)val); 960 val = cnf.GetBoolean(varname, (bool)val);
947 else if (typeof(T) == typeof(Int32)) 961 else if (typeof(T) == typeof(Int32))
@@ -949,8 +963,9 @@ namespace OpenSim.Framework
949 else if (typeof(T) == typeof(float)) 963 else if (typeof(T) == typeof(float))
950 val = cnf.GetFloat(varname, (int)val); 964 val = cnf.GetFloat(varname, (int)val);
951 else 965 else
952 m_log.WarnFormat("[UTIL]: Unhandled type {0}", typeof(T)); 966 m_log.ErrorFormat("[UTIL]: Unhandled type {0}", typeof(T));
953 } 967 }
968
954 return (T)val; 969 return (T)val;
955 } 970 }
956 971
diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
index d84460a..4c9ee06 100644
--- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
@@ -33,6 +33,7 @@ using log4net;
33using Nini.Config; 33using Nini.Config;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Framework.Monitoring;
36using OpenSim.Framework.Servers; 37using OpenSim.Framework.Servers;
37using OpenSim.Region.CoreModules.Framework.Monitoring.Alerts; 38using OpenSim.Region.CoreModules.Framework.Monitoring.Alerts;
38using OpenSim.Region.CoreModules.Framework.Monitoring.Monitors; 39using OpenSim.Region.CoreModules.Framework.Monitoring.Monitors;
@@ -100,6 +101,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
100 "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName), StatsPage); 101 "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName), StatsPage);
101 102
102 AddMonitors(); 103 AddMonitors();
104 RegisterStatsManagerRegionStatistics();
103 } 105 }
104 106
105 public void RemoveRegion(Scene scene) 107 public void RemoveRegion(Scene scene)
@@ -109,6 +111,9 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
109 111
110 MainServer.Instance.RemoveHTTPHandler("GET", "/monitorstats/" + m_scene.RegionInfo.RegionID); 112 MainServer.Instance.RemoveHTTPHandler("GET", "/monitorstats/" + m_scene.RegionInfo.RegionID);
111 MainServer.Instance.RemoveHTTPHandler("GET", "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName)); 113 MainServer.Instance.RemoveHTTPHandler("GET", "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName));
114
115 UnRegisterStatsManagerRegionStatistics();
116
112 m_scene = null; 117 m_scene = null;
113 } 118 }
114 119
@@ -399,6 +404,47 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
399 { 404 {
400 m_log.Error("[Monitor] " + reporter.Name + " for " + m_scene.RegionInfo.RegionName + " reports " + reason + " (Fatal: " + fatal + ")"); 405 m_log.Error("[Monitor] " + reporter.Name + " for " + m_scene.RegionInfo.RegionName + " reports " + reason + " (Fatal: " + fatal + ")");
401 } 406 }
407
408 private List<Stat> registeredStats = new List<Stat>();
409 private void MakeStat(string pName, string pUnitName, Action<Stat> act)
410 {
411 Stat tempStat = new Stat(pName, pName, pName, pUnitName, "scene", m_scene.RegionInfo.RegionName, StatType.Pull, act, StatVerbosity.Info);
412 StatsManager.RegisterStat(tempStat);
413 registeredStats.Add(tempStat);
414 }
415 private void RegisterStatsManagerRegionStatistics()
416 {
417 string regionName = m_scene.RegionInfo.RegionName;
418
419 MakeStat("RootAgents", "avatars", (s) => { s.Value = m_scene.SceneGraph.GetRootAgentCount(); });
420 MakeStat("ChildAgents", "avatars", (s) => { s.Value = m_scene.SceneGraph.GetChildAgentCount(); });
421 MakeStat("TotalPrims", "objects", (s) => { s.Value = m_scene.SceneGraph.GetTotalObjectsCount(); });
422 MakeStat("ActivePrims", "objects", (s) => { s.Value = m_scene.SceneGraph.GetActiveObjectsCount(); });
423 MakeStat("ActiveScripts", "scripts", (s) => { s.Value = m_scene.SceneGraph.GetActiveScriptsCount(); });
424
425 MakeStat("TimeDilation", "sec/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[0]; });
426 MakeStat("SimFPS", "fps", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[1]; });
427 MakeStat("PhysicsFPS", "fps", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[2]; });
428 MakeStat("AgentUpdates", "updates/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[3]; });
429 MakeStat("FrameTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[8]; });
430 MakeStat("NetTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[9]; });
431 MakeStat("OtherTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[12]; });
432 MakeStat("PhysicsTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[10]; });
433 MakeStat("AgentTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[16]; });
434 MakeStat("ImageTime", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[11]; });
435 MakeStat("ScriptLines", "lines/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[20]; });
436 MakeStat("SimSpareMS", "ms/sec", (s) => { s.Value = m_scene.StatsReporter.LastReportedSimStats[21]; });
437 }
438
439 private void UnRegisterStatsManagerRegionStatistics()
440 {
441 foreach (Stat stat in registeredStats)
442 {
443 StatsManager.DeregisterStat(stat);
444 stat.Dispose();
445 }
446 registeredStats.Clear();
447 }
402 448
403 } 449 }
404} 450} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
index ec94420..7b11658 100644
--- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
@@ -52,8 +52,8 @@ namespace OpenSim.Region.CoreModules.Hypergrid
52 52
53 public override void Initialise(IConfigSource config) 53 public override void Initialise(IConfigSource config)
54 { 54 {
55 IConfig startupConfig = config.Configs["Startup"]; 55 if (Util.GetConfigVarFromSections<string>(
56 if (startupConfig.GetString("WorldMapModule", "WorldMap") == "HGWorldMap") 56 config, "WorldMapModule", new string[] { "Map", "Startup" }, "WorldMap") == "HGWorldMap")
57 m_Enabled = true; 57 m_Enabled = true;
58 } 58 }
59 59
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
index e7065dc..40638f8 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
@@ -80,17 +80,14 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
80 bool generateMaptiles = true; 80 bool generateMaptiles = true;
81 Bitmap mapbmp; 81 Bitmap mapbmp;
82 82
83 try 83 string[] configSections = new string[] { "Map", "Startup" };
84 { 84
85 IConfig startupConfig = m_config.Configs["Startup"]; 85 drawPrimVolume
86 drawPrimVolume = startupConfig.GetBoolean("DrawPrimOnMapTile", drawPrimVolume); 86 = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, drawPrimVolume);
87 textureTerrain = startupConfig.GetBoolean("TextureOnMapTile", textureTerrain); 87 textureTerrain
88 generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", generateMaptiles); 88 = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, textureTerrain);
89 } 89 generateMaptiles
90 catch 90 = Util.GetConfigVarFromSections<bool>(m_config, "GenerateMaptiles", configSections, generateMaptiles);
91 {
92 m_log.Warn("[MAPTILE]: Failed to load StartupConfig");
93 }
94 91
95 if (generateMaptiles) 92 if (generateMaptiles)
96 { 93 {
@@ -148,9 +145,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
148 { 145 {
149 m_config = source; 146 m_config = source;
150 147
151 IConfig startupConfig = m_config.Configs["Startup"]; 148 if (Util.GetConfigVarFromSections<string>(
152 if (startupConfig.GetString("MapImageModule", "MapImageModule") != 149 m_config, "MapImageModule", new string[] { "Startup", "Map" }, "MapImageModule") != "MapImageModule")
153 "MapImageModule")
154 return; 150 return;
155 151
156 m_Enabled = true; 152 m_Enabled = true;
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
index 7ef44db..d38f34b 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -74,8 +74,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
74 { 74 {
75 m_config = source; 75 m_config = source;
76 76
77 IConfig startupConfig = m_config.Configs["Startup"]; 77 if (Util.GetConfigVarFromSections<string>(
78 if (startupConfig.GetString("MapImageModule", "MapImageModule") != "Warp3DImageModule") 78 m_config, "MapImageModule", new string[] { "Startup", "Map" }, "MapImageModule") != "Warp3DImageModule")
79 return; 79 return;
80 80
81 m_Enabled = true; 81 m_Enabled = true;
@@ -157,16 +157,12 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
157 bool drawPrimVolume = true; 157 bool drawPrimVolume = true;
158 bool textureTerrain = true; 158 bool textureTerrain = true;
159 159
160 try 160 string[] configSections = new string[] { "Map", "Startup" };
161 { 161
162 IConfig startupConfig = m_config.Configs["Startup"]; 162 drawPrimVolume
163 drawPrimVolume = startupConfig.GetBoolean("DrawPrimOnMapTile", drawPrimVolume); 163 = Util.GetConfigVarFromSections<bool>(m_config, "DrawPrimOnMapTile", configSections, drawPrimVolume);
164 textureTerrain = startupConfig.GetBoolean("TextureOnMapTile", textureTerrain); 164 textureTerrain
165 } 165 = Util.GetConfigVarFromSections<bool>(m_config, "TextureOnMapTile", configSections, textureTerrain);
166 catch
167 {
168 m_log.Warn("[WARP 3D IMAGE MODULE]: Failed to load StartupConfig");
169 }
170 166
171 m_colors.Clear(); 167 m_colors.Clear();
172 168
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index 2184a59..c868ee4 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -89,11 +89,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
89 #region INonSharedRegionModule Members 89 #region INonSharedRegionModule Members
90 public virtual void Initialise (IConfigSource config) 90 public virtual void Initialise (IConfigSource config)
91 { 91 {
92 IConfig startupConfig = config.Configs["Startup"]; 92 string[] configSections = new string[] { "Map", "Startup" };
93 if (startupConfig.GetString("WorldMapModule", "WorldMap") == "WorldMap") 93
94 if (Util.GetConfigVarFromSections<string>(
95 config, "WorldMapModule", configSections, "WorldMap") == "WorldMap")
94 m_Enabled = true; 96 m_Enabled = true;
95 97
96 blacklistTimeout = startupConfig.GetInt("BlacklistTimeout", 10*60) * 1000; 98 blacklistTimeout
99 = Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60) * 1000;
97 } 100 }
98 101
99 public virtual void AddRegion (Scene scene) 102 public virtual void AddRegion (Scene scene)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 1a1c3d2..a229a9a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -921,7 +921,11 @@ namespace OpenSim.Region.Framework.Scenes
921 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion); 921 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
922 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false); 922 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
923 923
924 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 924 string[] possibleMapConfigSections = new string[] { "Map", "Startup" };
925
926 m_generateMaptiles
927 = Util.GetConfigVarFromSections<bool>(config, "GenerateMaptiles", possibleMapConfigSections, true);
928
925 if (m_generateMaptiles) 929 if (m_generateMaptiles)
926 { 930 {
927 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0); 931 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0);
@@ -935,7 +939,10 @@ namespace OpenSim.Region.Framework.Scenes
935 } 939 }
936 else 940 else
937 { 941 {
938 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString()); 942 string tile
943 = Util.GetConfigVarFromSections<string>(
944 config, "MaptileStaticUUID", possibleMapConfigSections, UUID.Zero.ToString());
945
939 UUID tileID; 946 UUID tileID;
940 947
941 if (tile != UUID.Zero.ToString() && UUID.TryParse(tile, out tileID)) 948 if (tile != UUID.Zero.ToString() && UUID.TryParse(tile, out tileID))
diff --git a/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs b/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs
new file mode 100644
index 0000000..a3d2436
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs
@@ -0,0 +1,328 @@
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.Diagnostics;
31using System.Linq;
32using System.Net.NetworkInformation;
33using System.Text;
34using System.Threading;
35
36using log4net;
37using Mono.Addins;
38using Nini.Config;
39
40using OpenSim.Framework;
41using OpenSim.Framework.Console;
42using OpenSim.Framework.Monitoring;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45
46using OpenMetaverse.StructuredData;
47
48namespace OpenSim.Region.OptionalModules.Framework.Monitoring
49{
50[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ServerStatistics")]
51public class ServerStats : ISharedRegionModule
52{
53 private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
54 private readonly string LogHeader = "[SERVER STATS]";
55
56 public bool Enabled = false;
57 private static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>();
58
59 public readonly string CategoryServer = "server";
60
61 public readonly string ContainerProcessor = "processor";
62 public readonly string ContainerMemory = "memory";
63 public readonly string ContainerNetwork = "network";
64 public readonly string ContainerProcess = "process";
65
66 public string NetworkInterfaceTypes = "Ethernet";
67
68 readonly int performanceCounterSampleInterval = 500;
69 int lastperformanceCounterSampleTime = 0;
70
71 private class PerfCounterControl
72 {
73 public PerformanceCounter perfCounter;
74 public int lastFetch;
75 public string name;
76 public PerfCounterControl(PerformanceCounter pPc)
77 : this(pPc, String.Empty)
78 {
79 }
80 public PerfCounterControl(PerformanceCounter pPc, string pName)
81 {
82 perfCounter = pPc;
83 lastFetch = 0;
84 name = pName;
85 }
86 }
87
88 PerfCounterControl processorPercentPerfCounter = null;
89
90 #region ISharedRegionModule
91 // IRegionModuleBase.Name
92 public string Name { get { return "Server Stats"; } }
93 // IRegionModuleBase.ReplaceableInterface
94 public Type ReplaceableInterface { get { return null; } }
95 // IRegionModuleBase.Initialize
96 public void Initialise(IConfigSource source)
97 {
98 IConfig cfg = source.Configs["Monitoring"];
99
100 if (cfg != null)
101 Enabled = cfg.GetBoolean("ServerStatsEnabled", true);
102
103 if (Enabled)
104 {
105 NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet");
106 }
107 }
108 // IRegionModuleBase.Close
109 public void Close()
110 {
111 if (RegisteredStats.Count > 0)
112 {
113 foreach (Stat stat in RegisteredStats.Values)
114 {
115 StatsManager.DeregisterStat(stat);
116 stat.Dispose();
117 }
118 RegisteredStats.Clear();
119 }
120 }
121 // IRegionModuleBase.AddRegion
122 public void AddRegion(Scene scene)
123 {
124 }
125 // IRegionModuleBase.RemoveRegion
126 public void RemoveRegion(Scene scene)
127 {
128 }
129 // IRegionModuleBase.RegionLoaded
130 public void RegionLoaded(Scene scene)
131 {
132 }
133 // ISharedRegionModule.PostInitialize
134 public void PostInitialise()
135 {
136 if (RegisteredStats.Count == 0)
137 {
138 RegisterServerStats();
139 }
140 }
141 #endregion ISharedRegionModule
142
143 private void MakeStat(string pName, string pUnit, string pContainer, Action<Stat> act)
144 {
145 Stat stat = new Stat(pName, pName, "", pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Info);
146 StatsManager.RegisterStat(stat);
147 RegisteredStats.Add(pName, stat);
148 }
149
150 public void RegisterServerStats()
151 {
152 lastperformanceCounterSampleTime = Util.EnvironmentTickCount();
153 PerformanceCounter tempPC;
154 Stat tempStat;
155 string tempName;
156
157 try
158 {
159 tempName = "CPUPercent";
160 tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total");
161 processorPercentPerfCounter = new PerfCounterControl(tempPC);
162 // A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy.
163 tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor,
164 StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); },
165 StatVerbosity.Info);
166 StatsManager.RegisterStat(tempStat);
167 RegisteredStats.Add(tempName, tempStat);
168
169 MakeStat("TotalProcessorTime", "sec", ContainerProcessor,
170 (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; });
171
172 MakeStat("UserProcessorTime", "sec", ContainerProcessor,
173 (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; });
174
175 MakeStat("PrivilegedProcessorTime", "sec", ContainerProcessor,
176 (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; });
177
178 MakeStat("Threads", "threads", ContainerProcessor,
179 (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; });
180 }
181 catch (Exception e)
182 {
183 m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e);
184 }
185
186 try
187 {
188 List<string> okInterfaceTypes = new List<string>(NetworkInterfaceTypes.Split(','));
189
190 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces();
191 foreach (NetworkInterface nic in nics)
192 {
193 if (nic.OperationalStatus != OperationalStatus.Up)
194 continue;
195
196 string nicInterfaceType = nic.NetworkInterfaceType.ToString();
197 if (!okInterfaceTypes.Contains(nicInterfaceType))
198 {
199 m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'. To include, add to [Monitoring]NetworkInterfaceTypes='Ethernet,Loopback'",
200 LogHeader, nic.Name, nicInterfaceType);
201 continue;
202 }
203
204 if (nic.Supports(NetworkInterfaceComponent.IPv4))
205 {
206 IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics();
207 if (nicStats != null)
208 {
209 MakeStat("BytesRcvd/" + nic.Name, "KB", ContainerNetwork,
210 (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); });
211 MakeStat("BytesSent/" + nic.Name, "KB", ContainerNetwork,
212 (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); });
213 MakeStat("TotalBytes/" + nic.Name, "KB", ContainerNetwork,
214 (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); });
215 }
216 }
217 }
218 }
219 catch (Exception e)
220 {
221 m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e);
222 }
223
224 MakeStat("ProcessMemory", "MB", ContainerMemory,
225 (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; });
226 MakeStat("ObjectMemory", "MB", ContainerMemory,
227 (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; });
228 MakeStat("LastMemoryChurn", "MB/sec", ContainerMemory,
229 (s) => { s.Value = Math.Round(MemoryWatchdog.LastMemoryChurn * 1000d / 1024d / 1024d, 3); });
230 MakeStat("AverageMemoryChurn", "MB/sec", ContainerMemory,
231 (s) => { s.Value = Math.Round(MemoryWatchdog.AverageMemoryChurn * 1000d / 1024d / 1024d, 3); });
232 }
233
234 // Notes on performance counters:
235 // "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx
236 // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c
237 // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters
238 private delegate double PerfCounterNextValue();
239 private void GetNextValue(Stat stat, PerfCounterControl perfControl)
240 {
241 GetNextValue(stat, perfControl, 1.0);
242 }
243 private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor)
244 {
245 if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval)
246 {
247 if (perfControl != null && perfControl.perfCounter != null)
248 {
249 try
250 {
251 // Kludge for factor to run double duty. If -1, subtract the value from one
252 if (factor == -1)
253 stat.Value = 1 - perfControl.perfCounter.NextValue();
254 else
255 stat.Value = perfControl.perfCounter.NextValue() / factor;
256 }
257 catch (Exception e)
258 {
259 m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e);
260 }
261 perfControl.lastFetch = Util.EnvironmentTickCount();
262 }
263 }
264 }
265
266 private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat);
267 private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor)
268 {
269 // Get the one nic that has the name of this stat
270 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where(
271 (network) => network.Name == stat.Description);
272 try
273 {
274 foreach (NetworkInterface nic in nics)
275 {
276 IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics();
277 if (intrStats != null)
278 stat.Value = Math.Round(getter(intrStats) / factor, 3);
279 break;
280 }
281 }
282 catch
283 {
284 // There are times interfaces go away so we just won't update the stat for this
285 m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description);
286 }
287 }
288}
289
290public class ServerStatsAggregator : Stat
291{
292 public ServerStatsAggregator(
293 string shortName,
294 string name,
295 string description,
296 string unitName,
297 string category,
298 string container
299 )
300 : base(
301 shortName,
302 name,
303 description,
304 unitName,
305 category,
306 container,
307 StatType.Push,
308 MeasuresOfInterest.None,
309 null,
310 StatVerbosity.Info)
311 {
312 }
313 public override string ToConsoleString()
314 {
315 StringBuilder sb = new StringBuilder();
316
317 return sb.ToString();
318 }
319
320 public override OSDMap ToOSDMap()
321 {
322 OSDMap ret = new OSDMap();
323
324 return ret;
325 }
326}
327
328}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 1f186c3..f442ca2 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -204,7 +204,7 @@ public sealed class BSCharacter : BSPhysObject
204 // move. Thus, the velocity cannot be forced to zero. The problem is that small velocity 204 // move. Thus, the velocity cannot be forced to zero. The problem is that small velocity
205 // errors can creap in and the avatar will slowly float off in some direction. 205 // errors can creap in and the avatar will slowly float off in some direction.
206 // So, the problem is that, when an avatar is standing, we cannot tell creaping error 206 // So, the problem is that, when an avatar is standing, we cannot tell creaping error
207 // from real pushing.OMV.Vector3.Zero; 207 // from real pushing.
208 // The code below keeps setting the velocity to zero hoping the world will keep pushing. 208 // The code below keeps setting the velocity to zero hoping the world will keep pushing.
209 209
210 _velocityMotor.Step(timeStep); 210 _velocityMotor.Step(timeStep);
@@ -254,9 +254,11 @@ public sealed class BSCharacter : BSPhysObject
254 } 254 }
255 255
256 // If falling, we keep the world's downward vector no matter what the other axis specify. 256 // If falling, we keep the world's downward vector no matter what the other axis specify.
257 // The check for _velocity.Z < 0 makes jumping work (temporary upward force).
257 if (!Flying && !IsColliding) 258 if (!Flying && !IsColliding)
258 { 259 {
259 stepVelocity.Z = _velocity.Z; 260 if (_velocity.Z < 0)
261 stepVelocity.Z = _velocity.Z;
260 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity); 262 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
261 } 263 }
262 264
@@ -512,7 +514,7 @@ public sealed class BSCharacter : BSPhysObject
512 // just assign to "Position" because of potential call loops. 514 // just assign to "Position" because of potential call loops.
513 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() 515 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate()
514 { 516 {
515 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); 517 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
516 ForcePosition = _position; 518 ForcePosition = _position;
517 }); 519 });
518 ret = true; 520 ret = true;
@@ -572,7 +574,7 @@ public sealed class BSCharacter : BSPhysObject
572 m_targetVelocity = value; 574 m_targetVelocity = value;
573 OMV.Vector3 targetVel = value; 575 OMV.Vector3 targetVel = value;
574 if (_setAlwaysRun) 576 if (_setAlwaysRun)
575 targetVel *= BSParam.AvatarAlwaysRunFactor; 577 targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f);
576 578
577 PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate() 579 PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate()
578 { 580 {