diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Framework/Monitoring/BaseStatsCollector.cs | 26 | ||||
-rw-r--r-- | OpenSim/Framework/Monitoring/Checks/Check.cs | 8 | ||||
-rw-r--r-- | OpenSim/Framework/Monitoring/ChecksManager.cs | 45 | ||||
-rw-r--r-- | OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs | 2 | ||||
-rw-r--r-- | OpenSim/Framework/Monitoring/JobEngine.cs | 162 | ||||
-rw-r--r-- | OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs | 10 | ||||
-rw-r--r-- | OpenSim/Framework/Monitoring/ServerStatsCollector.cs | 77 | ||||
-rwxr-xr-x[-rw-r--r--] | OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs | 56 | ||||
-rwxr-xr-x[-rw-r--r--] | OpenSim/Framework/Monitoring/Stats/CounterStat.cs | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | OpenSim/Framework/Monitoring/Stats/EventHistogram.cs | 346 | ||||
-rw-r--r-- | OpenSim/Framework/Monitoring/Stats/Stat.cs | 51 | ||||
-rw-r--r-- | OpenSim/Framework/Monitoring/StatsLogger.cs | 6 | ||||
-rw-r--r-- | OpenSim/Framework/Monitoring/StatsManager.cs | 106 | ||||
-rw-r--r-- | OpenSim/Framework/Monitoring/Watchdog.cs | 61 | ||||
-rw-r--r-- | OpenSim/Framework/Monitoring/WorkManager.cs | 48 |
15 files changed, 558 insertions, 446 deletions
diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs index 20495f6..e513abd 100644 --- a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs | |||
@@ -43,7 +43,6 @@ namespace OpenSim.Framework.Monitoring | |||
43 | StringBuilder sb = new StringBuilder(Environment.NewLine); | 43 | StringBuilder sb = new StringBuilder(Environment.NewLine); |
44 | sb.Append("MEMORY STATISTICS"); | 44 | sb.Append("MEMORY STATISTICS"); |
45 | sb.Append(Environment.NewLine); | 45 | sb.Append(Environment.NewLine); |
46 | |||
47 | sb.AppendFormat( | 46 | sb.AppendFormat( |
48 | "Heap allocated to OpenSim : {0} MB\n", | 47 | "Heap allocated to OpenSim : {0} MB\n", |
49 | Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); | 48 | Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); |
@@ -56,13 +55,30 @@ namespace OpenSim.Framework.Monitoring | |||
56 | "Average heap allocation rate: {0} MB/s\n", | 55 | "Average heap allocation rate: {0} MB/s\n", |
57 | Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1024.0 / 1024, 3)); | 56 | Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1024.0 / 1024, 3)); |
58 | 57 | ||
59 | sb.AppendFormat( | 58 | Process myprocess = Process.GetCurrentProcess(); |
60 | "Process memory : {0} MB\n", | 59 | // if (!myprocess.HasExited) |
61 | Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0)); | 60 | try |
61 | { | ||
62 | myprocess.Refresh(); | ||
63 | sb.AppendFormat( | ||
64 | "Process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n", | ||
65 | Math.Round(myprocess.WorkingSet64 / 1024.0 / 1024.0), | ||
66 | Math.Round(myprocess.PagedMemorySize64 / 1024.0 / 1024.0), | ||
67 | Math.Round(myprocess.VirtualMemorySize64 / 1024.0 / 1024.0)); | ||
68 | sb.AppendFormat( | ||
69 | "Peak process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n", | ||
70 | Math.Round(myprocess.PeakWorkingSet64 / 1024.0 / 1024.0), | ||
71 | Math.Round(myprocess.PeakPagedMemorySize64 / 1024.0 / 1024.0), | ||
72 | Math.Round(myprocess.PeakVirtualMemorySize64 / 1024.0 / 1024.0)); | ||
73 | } | ||
74 | catch | ||
75 | { } | ||
76 | // else | ||
77 | // sb.Append("Process reported as Exited \n"); | ||
62 | 78 | ||
63 | return sb.ToString(); | 79 | return sb.ToString(); |
64 | } | 80 | } |
65 | 81 | ||
66 | public virtual string XReport(string uptime, string version) | 82 | public virtual string XReport(string uptime, string version) |
67 | { | 83 | { |
68 | return (string) Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0).ToString() ; | 84 | return (string) Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0).ToString() ; |
diff --git a/OpenSim/Framework/Monitoring/Checks/Check.cs b/OpenSim/Framework/Monitoring/Checks/Check.cs index 594386a..9a1bd45 100644 --- a/OpenSim/Framework/Monitoring/Checks/Check.cs +++ b/OpenSim/Framework/Monitoring/Checks/Check.cs | |||
@@ -79,7 +79,7 @@ namespace OpenSim.Framework.Monitoring | |||
79 | string category, | 79 | string category, |
80 | string container, | 80 | string container, |
81 | Func<Check, bool> checkFunc, | 81 | Func<Check, bool> checkFunc, |
82 | StatVerbosity verbosity) | 82 | StatVerbosity verbosity) |
83 | { | 83 | { |
84 | if (ChecksManager.SubCommands.Contains(category)) | 84 | if (ChecksManager.SubCommands.Contains(category)) |
85 | throw new Exception( | 85 | throw new Exception( |
@@ -108,9 +108,9 @@ namespace OpenSim.Framework.Monitoring | |||
108 | public virtual string ToConsoleString() | 108 | public virtual string ToConsoleString() |
109 | { | 109 | { |
110 | return string.Format( | 110 | return string.Format( |
111 | "{0}.{1}.{2} - {3}", | 111 | "{0}.{1}.{2} - {3}", |
112 | Category, | 112 | Category, |
113 | Container, | 113 | Container, |
114 | ShortName, | 114 | ShortName, |
115 | Description); | 115 | Description); |
116 | } | 116 | } |
diff --git a/OpenSim/Framework/Monitoring/ChecksManager.cs b/OpenSim/Framework/Monitoring/ChecksManager.cs index e4a7f8c..ff3b041 100644 --- a/OpenSim/Framework/Monitoring/ChecksManager.cs +++ b/OpenSim/Framework/Monitoring/ChecksManager.cs | |||
@@ -132,8 +132,8 @@ namespace OpenSim.Framework.Monitoring | |||
132 | /// <returns></returns> | 132 | /// <returns></returns> |
133 | public static bool RegisterCheck(Check check) | 133 | public static bool RegisterCheck(Check check) |
134 | { | 134 | { |
135 | SortedDictionary<string, SortedDictionary<string, Check>> category = null, newCategory; | 135 | SortedDictionary<string, SortedDictionary<string, Check>> category = null; |
136 | SortedDictionary<string, Check> container = null, newContainer; | 136 | SortedDictionary<string, Check> container = null; |
137 | 137 | ||
138 | lock (RegisteredChecks) | 138 | lock (RegisteredChecks) |
139 | { | 139 | { |
@@ -146,19 +146,15 @@ namespace OpenSim.Framework.Monitoring | |||
146 | // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed. | 146 | // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed. |
147 | // This means that we don't need to lock or copy them on iteration, which will be a much more | 147 | // This means that we don't need to lock or copy them on iteration, which will be a much more |
148 | // common operation after startup. | 148 | // common operation after startup. |
149 | if (container != null) | 149 | if (container == null) |
150 | newContainer = new SortedDictionary<string, Check>(container); | 150 | container = new SortedDictionary<string, Check>(); |
151 | else | ||
152 | newContainer = new SortedDictionary<string, Check>(); | ||
153 | 151 | ||
154 | if (category != null) | 152 | if (category == null) |
155 | newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>(category); | 153 | category = new SortedDictionary<string, SortedDictionary<string, Check>>(); |
156 | else | ||
157 | newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>(); | ||
158 | 154 | ||
159 | newContainer[check.ShortName] = check; | 155 | container[check.ShortName] = check; |
160 | newCategory[check.Container] = newContainer; | 156 | category[check.Container] = container; |
161 | RegisteredChecks[check.Category] = newCategory; | 157 | RegisteredChecks[check.Category] = category; |
162 | } | 158 | } |
163 | 159 | ||
164 | return true; | 160 | return true; |
@@ -171,23 +167,24 @@ namespace OpenSim.Framework.Monitoring | |||
171 | /// <returns></returns> | 167 | /// <returns></returns> |
172 | public static bool DeregisterCheck(Check check) | 168 | public static bool DeregisterCheck(Check check) |
173 | { | 169 | { |
174 | SortedDictionary<string, SortedDictionary<string, Check>> category = null, newCategory; | 170 | SortedDictionary<string, SortedDictionary<string, Check>> category = null; |
175 | SortedDictionary<string, Check> container = null, newContainer; | 171 | SortedDictionary<string, Check> container = null; |
176 | 172 | ||
177 | lock (RegisteredChecks) | 173 | lock (RegisteredChecks) |
178 | { | 174 | { |
179 | if (!TryGetCheckParents(check, out category, out container)) | 175 | if (!TryGetCheckParents(check, out category, out container)) |
180 | return false; | 176 | return false; |
181 | 177 | ||
182 | newContainer = new SortedDictionary<string, Check>(container); | 178 | if(container != null) |
183 | newContainer.Remove(check.ShortName); | 179 | { |
184 | 180 | container.Remove(check.ShortName); | |
185 | newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>(category); | 181 | if(category != null && container.Count == 0) |
186 | newCategory.Remove(check.Container); | 182 | { |
187 | 183 | category.Remove(check.Container); | |
188 | newCategory[check.Container] = newContainer; | 184 | if(category.Count == 0) |
189 | RegisteredChecks[check.Category] = newCategory; | 185 | RegisteredChecks.Remove(check.Category); |
190 | 186 | } | |
187 | } | ||
191 | return true; | 188 | return true; |
192 | } | 189 | } |
193 | } | 190 | } |
diff --git a/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs b/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs index 40df562..e326e8b 100644 --- a/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs | |||
@@ -39,7 +39,7 @@ namespace OpenSim.Framework.Monitoring | |||
39 | /// </summary> | 39 | /// </summary> |
40 | /// <returns></returns> | 40 | /// <returns></returns> |
41 | string Report(); | 41 | string Report(); |
42 | 42 | ||
43 | /// <summary> | 43 | /// <summary> |
44 | /// Report back collected statistical information in json | 44 | /// Report back collected statistical information in json |
45 | /// </summary> | 45 | /// </summary> |
diff --git a/OpenSim/Framework/Monitoring/JobEngine.cs b/OpenSim/Framework/Monitoring/JobEngine.cs index 6db9a67..115871e 100644 --- a/OpenSim/Framework/Monitoring/JobEngine.cs +++ b/OpenSim/Framework/Monitoring/JobEngine.cs | |||
@@ -40,6 +40,8 @@ namespace OpenSim.Framework.Monitoring | |||
40 | 40 | ||
41 | public int LogLevel { get; set; } | 41 | public int LogLevel { get; set; } |
42 | 42 | ||
43 | private object JobLock = new object(); | ||
44 | |||
43 | public string Name { get; private set; } | 45 | public string Name { get; private set; } |
44 | 46 | ||
45 | public string LoggingName { get; private set; } | 47 | public string LoggingName { get; private set; } |
@@ -47,7 +49,7 @@ namespace OpenSim.Framework.Monitoring | |||
47 | /// <summary> | 49 | /// <summary> |
48 | /// Is this engine running? | 50 | /// Is this engine running? |
49 | /// </summary> | 51 | /// </summary> |
50 | public bool IsRunning { get; private set; } | 52 | public bool IsRunning { get; private set; } |
51 | 53 | ||
52 | /// <summary> | 54 | /// <summary> |
53 | /// The current job that the engine is running. | 55 | /// The current job that the engine is running. |
@@ -55,7 +57,8 @@ namespace OpenSim.Framework.Monitoring | |||
55 | /// <remarks> | 57 | /// <remarks> |
56 | /// Will be null if no job is currently running. | 58 | /// Will be null if no job is currently running. |
57 | /// </remarks> | 59 | /// </remarks> |
58 | public Job CurrentJob { get; private set; } | 60 | private Job m_currentJob; |
61 | public Job CurrentJob { get { return m_currentJob;} } | ||
59 | 62 | ||
60 | /// <summary> | 63 | /// <summary> |
61 | /// Number of jobs waiting to be processed. | 64 | /// Number of jobs waiting to be processed. |
@@ -71,96 +74,64 @@ namespace OpenSim.Framework.Monitoring | |||
71 | /// Controls whether we need to warn in the log about exceeding the max queue size. | 74 | /// Controls whether we need to warn in the log about exceeding the max queue size. |
72 | /// </summary> | 75 | /// </summary> |
73 | /// <remarks> | 76 | /// <remarks> |
74 | /// This is flipped to false once queue max has been exceeded and back to true when it falls below max, in | 77 | /// This is flipped to false once queue max has been exceeded and back to true when it falls below max, in |
75 | /// order to avoid spamming the log with lots of warnings. | 78 | /// order to avoid spamming the log with lots of warnings. |
76 | /// </remarks> | 79 | /// </remarks> |
77 | private bool m_warnOverMaxQueue = true; | 80 | private bool m_warnOverMaxQueue = true; |
78 | 81 | ||
79 | private BlockingCollection<Job> m_jobQueue; | 82 | private BlockingCollection<Job> m_jobQueue = new BlockingCollection<Job>(new ConcurrentQueue<Job>(), 5000); |
80 | 83 | ||
81 | private CancellationTokenSource m_cancelSource; | 84 | private CancellationTokenSource m_cancelSource; |
82 | 85 | ||
83 | /// <summary> | 86 | private int m_timeout = -1; |
84 | /// Used to signal that we are ready to complete stop. | ||
85 | /// </summary> | ||
86 | private ManualResetEvent m_finishedProcessingAfterStop = new ManualResetEvent(false); | ||
87 | 87 | ||
88 | public JobEngine(string name, string loggingName) | 88 | private bool m_threadRunnig = false; |
89 | |||
90 | public JobEngine(string name, string loggingName, int timeout = -1) | ||
89 | { | 91 | { |
90 | Name = name; | 92 | Name = name; |
91 | LoggingName = loggingName; | 93 | LoggingName = loggingName; |
92 | 94 | m_timeout = timeout; | |
93 | RequestProcessTimeoutOnStop = 5000; | 95 | RequestProcessTimeoutOnStop = 5000; |
94 | } | 96 | } |
95 | 97 | ||
96 | public void Start() | 98 | public void Start() |
97 | { | 99 | { |
98 | lock (this) | 100 | lock (JobLock) |
99 | { | 101 | { |
100 | if (IsRunning) | 102 | if (IsRunning) |
101 | return; | 103 | return; |
102 | 104 | ||
103 | IsRunning = true; | 105 | IsRunning = true; |
104 | 106 | ||
105 | m_finishedProcessingAfterStop.Reset(); | ||
106 | |||
107 | m_jobQueue = new BlockingCollection<Job>(new ConcurrentQueue<Job>(), 5000); | ||
108 | m_cancelSource = new CancellationTokenSource(); | 107 | m_cancelSource = new CancellationTokenSource(); |
109 | 108 | WorkManager.RunInThreadPool(ProcessRequests, null, Name, false); | |
110 | WorkManager.StartThread( | 109 | m_threadRunnig = true; |
111 | ProcessRequests, | ||
112 | Name, | ||
113 | ThreadPriority.Normal, | ||
114 | false, | ||
115 | true, | ||
116 | null, | ||
117 | int.MaxValue); | ||
118 | } | 110 | } |
119 | } | 111 | } |
120 | 112 | ||
121 | public void Stop() | 113 | public void Stop() |
122 | { | 114 | { |
123 | lock (this) | 115 | lock (JobLock) |
124 | { | 116 | { |
125 | try | 117 | try |
126 | { | 118 | { |
127 | if (!IsRunning) | 119 | if (!IsRunning) |
128 | return; | 120 | return; |
129 | 121 | ||
130 | IsRunning = false; | 122 | m_log.DebugFormat("[JobEngine] Stopping {0}", Name); |
131 | 123 | ||
132 | int requestsLeft = m_jobQueue.Count; | 124 | IsRunning = false; |
133 | 125 | if(m_threadRunnig) | |
134 | if (requestsLeft <= 0) | ||
135 | { | 126 | { |
136 | m_cancelSource.Cancel(); | 127 | m_cancelSource.Cancel(); |
137 | } | 128 | m_threadRunnig = false; |
138 | else | ||
139 | { | ||
140 | m_log.InfoFormat("[{0}]: Waiting to write {1} events after stop.", LoggingName, requestsLeft); | ||
141 | |||
142 | while (requestsLeft > 0) | ||
143 | { | ||
144 | if (!m_finishedProcessingAfterStop.WaitOne(RequestProcessTimeoutOnStop)) | ||
145 | { | ||
146 | // After timeout no events have been written | ||
147 | if (requestsLeft == m_jobQueue.Count) | ||
148 | { | ||
149 | m_log.WarnFormat( | ||
150 | "[{0}]: No requests processed after {1} ms wait. Discarding remaining {2} requests", | ||
151 | LoggingName, RequestProcessTimeoutOnStop, requestsLeft); | ||
152 | |||
153 | break; | ||
154 | } | ||
155 | } | ||
156 | |||
157 | requestsLeft = m_jobQueue.Count; | ||
158 | } | ||
159 | } | 129 | } |
160 | } | 130 | } |
161 | finally | 131 | finally |
162 | { | 132 | { |
163 | m_cancelSource.Dispose(); | 133 | if(m_cancelSource != null) |
134 | m_cancelSource.Dispose(); | ||
164 | } | 135 | } |
165 | } | 136 | } |
166 | } | 137 | } |
@@ -169,7 +140,7 @@ namespace OpenSim.Framework.Monitoring | |||
169 | /// Make a job. | 140 | /// Make a job. |
170 | /// </summary> | 141 | /// </summary> |
171 | /// <remarks> | 142 | /// <remarks> |
172 | /// We provide this method to replace the constructor so that we can later pool job objects if necessary to | 143 | /// We provide this method to replace the constructor so that we can later pool job objects if necessary to |
173 | /// reduce memory churn. Normally one would directly call QueueJob() with parameters anyway. | 144 | /// reduce memory churn. Normally one would directly call QueueJob() with parameters anyway. |
174 | /// </remarks> | 145 | /// </remarks> |
175 | /// <returns></returns> | 146 | /// <returns></returns> |
@@ -219,6 +190,18 @@ namespace OpenSim.Framework.Monitoring | |||
219 | /// </param> | 190 | /// </param> |
220 | public bool QueueJob(Job job) | 191 | public bool QueueJob(Job job) |
221 | { | 192 | { |
193 | lock(JobLock) | ||
194 | { | ||
195 | if(!IsRunning) | ||
196 | return false; | ||
197 | |||
198 | if(!m_threadRunnig) | ||
199 | { | ||
200 | WorkManager.RunInThreadPool(ProcessRequests, null, Name, false); | ||
201 | m_threadRunnig = true; | ||
202 | } | ||
203 | } | ||
204 | |||
222 | if (m_jobQueue.Count < m_jobQueue.BoundedCapacity) | 205 | if (m_jobQueue.Count < m_jobQueue.BoundedCapacity) |
223 | { | 206 | { |
224 | m_jobQueue.Add(job); | 207 | m_jobQueue.Add(job); |
@@ -238,56 +221,53 @@ namespace OpenSim.Framework.Monitoring | |||
238 | 221 | ||
239 | m_warnOverMaxQueue = false; | 222 | m_warnOverMaxQueue = false; |
240 | } | 223 | } |
241 | |||
242 | return false; | 224 | return false; |
243 | } | 225 | } |
244 | } | 226 | } |
245 | 227 | ||
246 | private void ProcessRequests() | 228 | private void ProcessRequests(Object o) |
247 | { | 229 | { |
248 | try | 230 | while(IsRunning) |
249 | { | 231 | { |
250 | while (IsRunning || m_jobQueue.Count > 0) | 232 | try |
251 | { | 233 | { |
252 | try | 234 | if(!m_jobQueue.TryTake(out m_currentJob, m_timeout, m_cancelSource.Token)) |
253 | { | 235 | { |
254 | CurrentJob = m_jobQueue.Take(m_cancelSource.Token); | 236 | lock(JobLock) |
255 | } | 237 | m_threadRunnig = false; |
256 | catch (ObjectDisposedException e) | 238 | break; |
257 | { | ||
258 | // If we see this whilst not running then it may be due to a race where this thread checks | ||
259 | // IsRunning after the stopping thread sets it to false and disposes of the cancellation source. | ||
260 | if (IsRunning) | ||
261 | throw e; | ||
262 | else | ||
263 | break; | ||
264 | } | 239 | } |
240 | } | ||
241 | catch(ObjectDisposedException e) | ||
242 | { | ||
243 | m_log.DebugFormat("[JobEngine] {0} stopping ignoring {1} jobs in queue", | ||
244 | Name,m_jobQueue.Count); | ||
245 | break; | ||
246 | } | ||
247 | catch(OperationCanceledException) | ||
248 | { | ||
249 | break; | ||
250 | } | ||
265 | 251 | ||
266 | if (LogLevel >= 1) | 252 | if(LogLevel >= 1) |
267 | m_log.DebugFormat("[{0}]: Processing job {1}", LoggingName, CurrentJob.Name); | 253 | m_log.DebugFormat("[{0}]: Processing job {1}",LoggingName,m_currentJob.Name); |
268 | 254 | ||
269 | try | 255 | try |
270 | { | 256 | { |
271 | CurrentJob.Action(); | 257 | m_currentJob.Action(); |
272 | } | 258 | } |
273 | catch (Exception e) | 259 | catch(Exception e) |
274 | { | 260 | { |
275 | m_log.Error( | 261 | m_log.Error( |
276 | string.Format( | 262 | string.Format( |
277 | "[{0}]: Job {1} failed, continuing. Exception ", LoggingName, CurrentJob.Name), e); | 263 | "[{0}]: Job {1} failed, continuing. Exception ",LoggingName,m_currentJob.Name),e); |
278 | } | 264 | } |
279 | 265 | ||
280 | if (LogLevel >= 1) | 266 | if(LogLevel >= 1) |
281 | m_log.DebugFormat("[{0}]: Processed job {1}", LoggingName, CurrentJob.Name); | 267 | m_log.DebugFormat("[{0}]: Processed job {1}",LoggingName,m_currentJob.Name); |
282 | 268 | ||
283 | CurrentJob = null; | 269 | m_currentJob = null; |
284 | } | ||
285 | } | ||
286 | catch (OperationCanceledException) | ||
287 | { | ||
288 | } | 270 | } |
289 | |||
290 | m_finishedProcessingAfterStop.Set(); | ||
291 | } | 271 | } |
292 | 272 | ||
293 | public class Job | 273 | public class Job |
@@ -320,7 +300,7 @@ namespace OpenSim.Framework.Monitoring | |||
320 | CommonId = commonId; | 300 | CommonId = commonId; |
321 | Action = action; | 301 | Action = action; |
322 | } | 302 | } |
323 | 303 | ||
324 | /// <summary> | 304 | /// <summary> |
325 | /// Make a job. It needs to be separately queued. | 305 | /// Make a job. It needs to be separately queued. |
326 | /// </summary> | 306 | /// </summary> |
@@ -338,4 +318,4 @@ namespace OpenSim.Framework.Monitoring | |||
338 | } | 318 | } |
339 | } | 319 | } |
340 | } | 320 | } |
341 | } \ No newline at end of file | 321 | } |
diff --git a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs index a617b93..2ff2014 100644 --- a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs +++ b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs | |||
@@ -2,7 +2,7 @@ | |||
2 | using System.Runtime.CompilerServices; | 2 | using System.Runtime.CompilerServices; |
3 | using System.Runtime.InteropServices; | 3 | using System.Runtime.InteropServices; |
4 | 4 | ||
5 | // General Information about an assembly is controlled through the following | 5 | // General Information about an assembly is controlled through the following |
6 | // set of attributes. Change these attribute values to modify the information | 6 | // set of attributes. Change these attribute values to modify the information |
7 | // associated with an assembly. | 7 | // associated with an assembly. |
8 | [assembly: AssemblyTitle("OpenSim.Framework.Monitoring")] | 8 | [assembly: AssemblyTitle("OpenSim.Framework.Monitoring")] |
@@ -14,8 +14,8 @@ using System.Runtime.InteropServices; | |||
14 | [assembly: AssemblyTrademark("")] | 14 | [assembly: AssemblyTrademark("")] |
15 | [assembly: AssemblyCulture("")] | 15 | [assembly: AssemblyCulture("")] |
16 | 16 | ||
17 | // Setting ComVisible to false makes the types in this assembly not visible | 17 | // Setting ComVisible to false makes the types in this assembly not visible |
18 | // to COM components. If you need to access a type in this assembly from | 18 | // to COM components. If you need to access a type in this assembly from |
19 | // COM, set the ComVisible attribute to true on that type. | 19 | // COM, set the ComVisible attribute to true on that type. |
20 | [assembly: ComVisible(false)] | 20 | [assembly: ComVisible(false)] |
21 | 21 | ||
@@ -25,9 +25,9 @@ using System.Runtime.InteropServices; | |||
25 | // Version information for an assembly consists of the following four values: | 25 | // Version information for an assembly consists of the following four values: |
26 | // | 26 | // |
27 | // Major Version | 27 | // Major Version |
28 | // Minor Version | 28 | // Minor Version |
29 | // Build Number | 29 | // Build Number |
30 | // Revision | 30 | // Revision |
31 | // | 31 | // |
32 | [assembly: AssemblyVersion("0.8.3.*")] | 32 | [assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)] |
33 | 33 | ||
diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index 77315bb..a26a6e0 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs | |||
@@ -88,7 +88,7 @@ namespace OpenSim.Framework.Monitoring | |||
88 | IConfig cfg = source.Configs["Monitoring"]; | 88 | IConfig cfg = source.Configs["Monitoring"]; |
89 | 89 | ||
90 | if (cfg != null) | 90 | if (cfg != null) |
91 | Enabled = cfg.GetBoolean("ServerStatsEnabled", true); | 91 | Enabled = cfg.GetBoolean("ServerStatsEnabled", false); |
92 | 92 | ||
93 | if (Enabled) | 93 | if (Enabled) |
94 | { | 94 | { |
@@ -98,12 +98,18 @@ namespace OpenSim.Framework.Monitoring | |||
98 | 98 | ||
99 | public void Start() | 99 | public void Start() |
100 | { | 100 | { |
101 | if(!Enabled) | ||
102 | return; | ||
103 | |||
101 | if (RegisteredStats.Count == 0) | 104 | if (RegisteredStats.Count == 0) |
102 | RegisterServerStats(); | 105 | RegisterServerStats(); |
103 | } | 106 | } |
104 | 107 | ||
105 | public void Close() | 108 | public void Close() |
106 | { | 109 | { |
110 | if(!Enabled) | ||
111 | return; | ||
112 | |||
107 | if (RegisteredStats.Count > 0) | 113 | if (RegisteredStats.Count > 0) |
108 | { | 114 | { |
109 | foreach (Stat stat in RegisteredStats.Values) | 115 | foreach (Stat stat in RegisteredStats.Values) |
@@ -167,18 +173,18 @@ namespace OpenSim.Framework.Monitoring | |||
167 | } | 173 | } |
168 | 174 | ||
169 | MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerThreadpool, | 175 | MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerThreadpool, |
170 | s => | 176 | s => |
171 | { | 177 | { |
172 | int workerThreads, iocpThreads; | 178 | int workerThreads, iocpThreads; |
173 | ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads); | 179 | ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads); |
174 | s.Value = workerThreads; | 180 | s.Value = workerThreads; |
175 | }); | 181 | }); |
176 | 182 | ||
177 | MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerThreadpool, | 183 | MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerThreadpool, |
178 | s => | 184 | s => |
179 | { | 185 | { |
180 | int workerThreads, iocpThreads; | 186 | int workerThreads, iocpThreads; |
181 | ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads); | 187 | ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads); |
182 | s.Value = iocpThreads; | 188 | s.Value = iocpThreads; |
183 | }); | 189 | }); |
184 | 190 | ||
@@ -193,10 +199,10 @@ namespace OpenSim.Framework.Monitoring | |||
193 | } | 199 | } |
194 | 200 | ||
195 | MakeStat( | 201 | MakeStat( |
196 | "HTTPRequestsMade", | 202 | "HTTPRequestsMade", |
197 | "Number of outbound HTTP requests made", | 203 | "Number of outbound HTTP requests made", |
198 | "requests", | 204 | "requests", |
199 | ContainerNetwork, | 205 | ContainerNetwork, |
200 | s => s.Value = WebUtil.RequestNumber, | 206 | s => s.Value = WebUtil.RequestNumber, |
201 | MeasuresOfInterest.AverageChangeOverTime); | 207 | MeasuresOfInterest.AverageChangeOverTime); |
202 | 208 | ||
@@ -249,9 +255,52 @@ namespace OpenSim.Framework.Monitoring | |||
249 | (s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); }); | 255 | (s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); }); |
250 | MakeStat("AverageHeapAllocationRate", null, "MB/sec", ContainerMemory, | 256 | MakeStat("AverageHeapAllocationRate", null, "MB/sec", ContainerMemory, |
251 | (s) => { s.Value = Math.Round(MemoryWatchdog.AverageHeapAllocationRate * 1000d / 1024d / 1024d, 3); }); | 257 | (s) => { s.Value = Math.Round(MemoryWatchdog.AverageHeapAllocationRate * 1000d / 1024d / 1024d, 3); }); |
258 | |||
259 | MakeStat("ProcessResident", null, "MB", ContainerProcess, | ||
260 | (s) => | ||
261 | { | ||
262 | Process myprocess = Process.GetCurrentProcess(); | ||
263 | myprocess.Refresh(); | ||
264 | s.Value = Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0); | ||
265 | }); | ||
266 | MakeStat("ProcessPaged", null, "MB", ContainerProcess, | ||
267 | (s) => | ||
268 | { | ||
269 | Process myprocess = Process.GetCurrentProcess(); | ||
270 | myprocess.Refresh(); | ||
271 | s.Value = Math.Round(Process.GetCurrentProcess().PagedMemorySize64 / 1024.0 / 1024.0); | ||
272 | }); | ||
273 | MakeStat("ProcessVirtual", null, "MB", ContainerProcess, | ||
274 | (s) => | ||
275 | { | ||
276 | Process myprocess = Process.GetCurrentProcess(); | ||
277 | myprocess.Refresh(); | ||
278 | s.Value = Math.Round(Process.GetCurrentProcess().VirtualMemorySize64 / 1024.0 / 1024.0); | ||
279 | }); | ||
280 | MakeStat("PeakProcessResident", null, "MB", ContainerProcess, | ||
281 | (s) => | ||
282 | { | ||
283 | Process myprocess = Process.GetCurrentProcess(); | ||
284 | myprocess.Refresh(); | ||
285 | s.Value = Math.Round(Process.GetCurrentProcess().PeakWorkingSet64 / 1024.0 / 1024.0); | ||
286 | }); | ||
287 | MakeStat("PeakProcessPaged", null, "MB", ContainerProcess, | ||
288 | (s) => | ||
289 | { | ||
290 | Process myprocess = Process.GetCurrentProcess(); | ||
291 | myprocess.Refresh(); | ||
292 | s.Value = Math.Round(Process.GetCurrentProcess().PeakPagedMemorySize64 / 1024.0 / 1024.0); | ||
293 | }); | ||
294 | MakeStat("PeakProcessVirtual", null, "MB", ContainerProcess, | ||
295 | (s) => | ||
296 | { | ||
297 | Process myprocess = Process.GetCurrentProcess(); | ||
298 | myprocess.Refresh(); | ||
299 | s.Value = Math.Round(Process.GetCurrentProcess().PeakVirtualMemorySize64 / 1024.0 / 1024.0); | ||
300 | }); | ||
252 | } | 301 | } |
253 | 302 | ||
254 | // Notes on performance counters: | 303 | // Notes on performance counters: |
255 | // "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx | 304 | // "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx |
256 | // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c | 305 | // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c |
257 | // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters | 306 | // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters |
diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs index e4df7ee..88a0297 100644..100755 --- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs | |||
@@ -34,6 +34,7 @@ using OpenMetaverse; | |||
34 | using OpenMetaverse.StructuredData; | 34 | using OpenMetaverse.StructuredData; |
35 | using OpenSim.Framework.Monitoring.Interfaces; | 35 | using OpenSim.Framework.Monitoring.Interfaces; |
36 | 36 | ||
37 | |||
37 | namespace OpenSim.Framework.Monitoring | 38 | namespace OpenSim.Framework.Monitoring |
38 | { | 39 | { |
39 | /// <summary> | 40 | /// <summary> |
@@ -71,6 +72,11 @@ namespace OpenSim.Framework.Monitoring | |||
71 | private volatile float pendingDownloads; | 72 | private volatile float pendingDownloads; |
72 | private volatile float pendingUploads; | 73 | private volatile float pendingUploads; |
73 | private volatile float activeScripts; | 74 | private volatile float activeScripts; |
75 | private volatile float spareTime; | ||
76 | private volatile float sleepTime; | ||
77 | private volatile float physicsStep; | ||
78 | |||
79 | |||
74 | private volatile float scriptLinesPerSecond; | 80 | private volatile float scriptLinesPerSecond; |
75 | private volatile float m_frameDilation; | 81 | private volatile float m_frameDilation; |
76 | private volatile float m_usersLoggingIn; | 82 | private volatile float m_usersLoggingIn; |
@@ -84,17 +90,17 @@ namespace OpenSim.Framework.Monitoring | |||
84 | // /// haven't yet been implemented... | 90 | // /// haven't yet been implemented... |
85 | // /// </summary> | 91 | // /// </summary> |
86 | // public long AssetsInCache { get { return assetsInCache; } } | 92 | // public long AssetsInCache { get { return assetsInCache; } } |
87 | // | 93 | // |
88 | // /// <value> | 94 | // /// <value> |
89 | // /// Currently unused | 95 | // /// Currently unused |
90 | // /// </value> | 96 | // /// </value> |
91 | // public long TexturesInCache { get { return texturesInCache; } } | 97 | // public long TexturesInCache { get { return texturesInCache; } } |
92 | // | 98 | // |
93 | // /// <value> | 99 | // /// <value> |
94 | // /// Currently misleading since we can't currently subtract removed asset memory usage without a performance hit | 100 | // /// Currently misleading since we can't currently subtract removed asset memory usage without a performance hit |
95 | // /// </value> | 101 | // /// </value> |
96 | // public long AssetCacheMemoryUsage { get { return assetCacheMemoryUsage; } } | 102 | // public long AssetCacheMemoryUsage { get { return assetCacheMemoryUsage; } } |
97 | // | 103 | // |
98 | // /// <value> | 104 | // /// <value> |
99 | // /// Currently unused | 105 | // /// Currently unused |
100 | // /// </value> | 106 | // /// </value> |
@@ -121,7 +127,7 @@ namespace OpenSim.Framework.Monitoring | |||
121 | public float PendingUploads { get { return pendingUploads; } } | 127 | public float PendingUploads { get { return pendingUploads; } } |
122 | public float ActiveScripts { get { return activeScripts; } } | 128 | public float ActiveScripts { get { return activeScripts; } } |
123 | public float ScriptLinesPerSecond { get { return scriptLinesPerSecond; } } | 129 | public float ScriptLinesPerSecond { get { return scriptLinesPerSecond; } } |
124 | 130 | ||
125 | // /// <summary> | 131 | // /// <summary> |
126 | // /// This is the time it took for the last asset request made in response to a cache miss. | 132 | // /// This is the time it took for the last asset request made in response to a cache miss. |
127 | // /// </summary> | 133 | // /// </summary> |
@@ -171,7 +177,7 @@ namespace OpenSim.Framework.Monitoring | |||
171 | // assetsInCache++; | 177 | // assetsInCache++; |
172 | // //assetCacheMemoryUsage += asset.Data.Length; | 178 | // //assetCacheMemoryUsage += asset.Data.Length; |
173 | // } | 179 | // } |
174 | // | 180 | // |
175 | // public void RemoveAsset(UUID uuid) | 181 | // public void RemoveAsset(UUID uuid) |
176 | // { | 182 | // { |
177 | // assetsInCache--; | 183 | // assetsInCache--; |
@@ -198,7 +204,7 @@ namespace OpenSim.Framework.Monitoring | |||
198 | // texturesInCache = 0; | 204 | // texturesInCache = 0; |
199 | // textureCacheMemoryUsage = 0; | 205 | // textureCacheMemoryUsage = 0; |
200 | // } | 206 | // } |
201 | // | 207 | // |
202 | // public void AddAssetRequestTimeAfterCacheMiss(TimeSpan ts) | 208 | // public void AddAssetRequestTimeAfterCacheMiss(TimeSpan ts) |
203 | // { | 209 | // { |
204 | // assetRequestTimeAfterCacheMiss = ts; | 210 | // assetRequestTimeAfterCacheMiss = ts; |
@@ -253,7 +259,7 @@ namespace OpenSim.Framework.Monitoring | |||
253 | /// <param name="pack"></param> | 259 | /// <param name="pack"></param> |
254 | public void ReceiveClassicSimStatsPacket(SimStats stats) | 260 | public void ReceiveClassicSimStatsPacket(SimStats stats) |
255 | { | 261 | { |
256 | // FIXME: SimStats shouldn't allow an arbitrary stat packing order (which is inherited from the original | 262 | // FIXME: SimStats shouldn't allow an arbitrary stat packing order (which is inherited from the original |
257 | // SimStatsPacket that was being used). | 263 | // SimStatsPacket that was being used). |
258 | 264 | ||
259 | // For an unknown reason the original designers decided not to | 265 | // For an unknown reason the original designers decided not to |
@@ -270,8 +276,8 @@ namespace OpenSim.Framework.Monitoring | |||
270 | totalFrameTime = stats.StatsBlock[8].StatValue; | 276 | totalFrameTime = stats.StatsBlock[8].StatValue; |
271 | netFrameTime = stats.StatsBlock[9].StatValue; | 277 | netFrameTime = stats.StatsBlock[9].StatValue; |
272 | physicsFrameTime = stats.StatsBlock[10].StatValue; | 278 | physicsFrameTime = stats.StatsBlock[10].StatValue; |
273 | otherFrameTime = stats.StatsBlock[11].StatValue; | 279 | imageFrameTime = stats.StatsBlock[11].StatValue; |
274 | imageFrameTime = stats.StatsBlock[12].StatValue; | 280 | otherFrameTime = stats.StatsBlock[12].StatValue; |
275 | inPacketsPerSecond = stats.StatsBlock[13].StatValue; | 281 | inPacketsPerSecond = stats.StatsBlock[13].StatValue; |
276 | outPacketsPerSecond = stats.StatsBlock[14].StatValue; | 282 | outPacketsPerSecond = stats.StatsBlock[14].StatValue; |
277 | unackedBytes = stats.StatsBlock[15].StatValue; | 283 | unackedBytes = stats.StatsBlock[15].StatValue; |
@@ -279,12 +285,16 @@ namespace OpenSim.Framework.Monitoring | |||
279 | pendingDownloads = stats.StatsBlock[17].StatValue; | 285 | pendingDownloads = stats.StatsBlock[17].StatValue; |
280 | pendingUploads = stats.StatsBlock[18].StatValue; | 286 | pendingUploads = stats.StatsBlock[18].StatValue; |
281 | activeScripts = stats.StatsBlock[19].StatValue; | 287 | activeScripts = stats.StatsBlock[19].StatValue; |
282 | scriptLinesPerSecond = stats.StatsBlock[20].StatValue; | 288 | sleepTime = stats.StatsBlock[20].StatValue; |
283 | m_frameDilation = stats.StatsBlock[22].StatValue; | 289 | spareTime = stats.StatsBlock[21].StatValue; |
284 | m_usersLoggingIn = stats.StatsBlock[23].StatValue; | 290 | physicsStep = stats.StatsBlock[22].StatValue; |
285 | m_totalGeoPrims = stats.StatsBlock[24].StatValue; | 291 | |
286 | m_totalMeshes = stats.StatsBlock[25].StatValue; | 292 | scriptLinesPerSecond = stats.ExtraStatsBlock[0].StatValue; |
287 | m_inUseThreads = stats.StatsBlock[26].StatValue; | 293 | m_frameDilation = stats.ExtraStatsBlock[1].StatValue; |
294 | m_usersLoggingIn = stats.ExtraStatsBlock[2].StatValue; | ||
295 | m_totalGeoPrims = stats.ExtraStatsBlock[3].StatValue; | ||
296 | m_totalMeshes = stats.ExtraStatsBlock[4].StatValue; | ||
297 | m_inUseThreads = stats.ExtraStatsBlock[5].StatValue; | ||
288 | } | 298 | } |
289 | 299 | ||
290 | /// <summary> | 300 | /// <summary> |
@@ -296,7 +306,7 @@ namespace OpenSim.Framework.Monitoring | |||
296 | StringBuilder sb = new StringBuilder(Environment.NewLine); | 306 | StringBuilder sb = new StringBuilder(Environment.NewLine); |
297 | // sb.Append("ASSET STATISTICS"); | 307 | // sb.Append("ASSET STATISTICS"); |
298 | // sb.Append(Environment.NewLine); | 308 | // sb.Append(Environment.NewLine); |
299 | 309 | ||
300 | /* | 310 | /* |
301 | sb.Append( | 311 | sb.Append( |
302 | string.Format( | 312 | string.Format( |
@@ -332,7 +342,7 @@ Asset service request failures: {3}" + Environment.NewLine, | |||
332 | List<Stat> stats = StatsManager.GetStatsFromEachContainer("clientstack", "ClientLogoutsDueToNoReceives"); | 342 | List<Stat> stats = StatsManager.GetStatsFromEachContainer("clientstack", "ClientLogoutsDueToNoReceives"); |
333 | 343 | ||
334 | sb.AppendFormat( | 344 | sb.AppendFormat( |
335 | "Client logouts due to no data receive timeout: {0}\n\n", | 345 | "Client logouts due to no data receive timeout: {0}\n\n", |
336 | stats != null ? stats.Sum(s => s.Value).ToString() : "unknown"); | 346 | stats != null ? stats.Sum(s => s.Value).ToString() : "unknown"); |
337 | 347 | ||
338 | // sb.Append(Environment.NewLine); | 348 | // sb.Append(Environment.NewLine); |
@@ -433,10 +443,10 @@ Asset service request failures: {3}" + Environment.NewLine, | |||
433 | foreach (ProcessThread currentThread in | 443 | foreach (ProcessThread currentThread in |
434 | Process.GetCurrentProcess().Threads) | 444 | Process.GetCurrentProcess().Threads) |
435 | { | 445 | { |
436 | // A known issue with the current process .Threads property is | 446 | // A known issue with the current process .Threads property is |
437 | // that it can return null threads, thus don't count those as | 447 | // that it can return null threads, thus don't count those as |
438 | // running threads and prevent the program function from failing | 448 | // running threads and prevent the program function from failing |
439 | if (currentThread != null && | 449 | if (currentThread != null && |
440 | currentThread.ThreadState == ThreadState.Running) | 450 | currentThread.ThreadState == ThreadState.Running) |
441 | { | 451 | { |
442 | numberThreadsRunning++; | 452 | numberThreadsRunning++; |
@@ -495,7 +505,7 @@ Asset service request failures: {3}" + Environment.NewLine, | |||
495 | "{0:0.##}", numberThreadsRunning)); | 505 | "{0:0.##}", numberThreadsRunning)); |
496 | args["ProcMem"] = OSD.FromString(String.Format("{0:#,###,###.##}", | 506 | args["ProcMem"] = OSD.FromString(String.Format("{0:#,###,###.##}", |
497 | memUsage)); | 507 | memUsage)); |
498 | 508 | ||
499 | return args; | 509 | return args; |
500 | } | 510 | } |
501 | } | 511 | } |
@@ -521,12 +531,12 @@ Asset service request failures: {3}" + Environment.NewLine, | |||
521 | { | 531 | { |
522 | return m_statsProvider.GetStats(); | 532 | return m_statsProvider.GetStats(); |
523 | } | 533 | } |
524 | 534 | ||
525 | public string XReport(string uptime, string version) | 535 | public string XReport(string uptime, string version) |
526 | { | 536 | { |
527 | return ""; | 537 | return ""; |
528 | } | 538 | } |
529 | 539 | ||
530 | public OSDMap OReport(string uptime, string version) | 540 | public OSDMap OReport(string uptime, string version) |
531 | { | 541 | { |
532 | OSDMap ret = new OSDMap(); | 542 | OSDMap ret = new OSDMap(); |
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 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Linq; | 30 | using System.Linq; |
31 | using System.Text; | 31 | using System.Text; |
32 | 32 | ||
33 | using OpenMetaverse.StructuredData; | 33 | using OpenMetaverse.StructuredData; |
34 | 34 | ||
35 | namespace OpenSim.Framework.Monitoring | 35 | namespace 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) |
41 | public class EventHistogram | 41 | public 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 | } |
diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs index a644fa5..9cac451 100644 --- a/OpenSim/Framework/Monitoring/Watchdog.cs +++ b/OpenSim/Framework/Monitoring/Watchdog.cs | |||
@@ -96,7 +96,7 @@ namespace OpenSim.Framework.Monitoring | |||
96 | FirstTick = Environment.TickCount & Int32.MaxValue; | 96 | FirstTick = Environment.TickCount & Int32.MaxValue; |
97 | LastTick = FirstTick; | 97 | LastTick = FirstTick; |
98 | 98 | ||
99 | Stat | 99 | Stat |
100 | = new Stat( | 100 | = new Stat( |
101 | name, | 101 | name, |
102 | string.Format("Last update of thread {0}", name), | 102 | string.Format("Last update of thread {0}", name), |
@@ -180,6 +180,30 @@ namespace OpenSim.Framework.Monitoring | |||
180 | m_watchdogTimer.Elapsed += WatchdogTimerElapsed; | 180 | m_watchdogTimer.Elapsed += WatchdogTimerElapsed; |
181 | } | 181 | } |
182 | 182 | ||
183 | public static void Stop() | ||
184 | { | ||
185 | if(m_threads == null) | ||
186 | return; | ||
187 | |||
188 | lock(m_threads) | ||
189 | { | ||
190 | m_enabled = false; | ||
191 | if(m_watchdogTimer != null) | ||
192 | { | ||
193 | m_watchdogTimer.Dispose(); | ||
194 | m_watchdogTimer = null; | ||
195 | } | ||
196 | |||
197 | foreach(ThreadWatchdogInfo twi in m_threads.Values) | ||
198 | { | ||
199 | Thread t = twi.Thread; | ||
200 | if(t.IsAlive) | ||
201 | t.Abort(); | ||
202 | } | ||
203 | m_threads.Clear(); | ||
204 | } | ||
205 | } | ||
206 | |||
183 | /// <summary> | 207 | /// <summary> |
184 | /// Add a thread to the watchdog tracker. | 208 | /// Add a thread to the watchdog tracker. |
185 | /// </summary> | 209 | /// </summary> |
@@ -230,14 +254,12 @@ namespace OpenSim.Framework.Monitoring | |||
230 | 254 | ||
231 | twi.Cleanup(); | 255 | twi.Cleanup(); |
232 | m_threads.Remove(threadID); | 256 | m_threads.Remove(threadID); |
233 | |||
234 | return true; | 257 | return true; |
235 | } | 258 | } |
236 | else | 259 | else |
237 | { | 260 | { |
238 | m_log.WarnFormat( | 261 | m_log.WarnFormat( |
239 | "[WATCHDOG]: Requested to remove thread with ID {0} but this is not being monitored", threadID); | 262 | "[WATCHDOG]: Requested to remove thread with ID {0} but this is not being monitored", threadID); |
240 | |||
241 | return false; | 263 | return false; |
242 | } | 264 | } |
243 | } | 265 | } |
@@ -317,6 +339,8 @@ namespace OpenSim.Framework.Monitoring | |||
317 | /// <param name="e"></param> | 339 | /// <param name="e"></param> |
318 | private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) | 340 | private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) |
319 | { | 341 | { |
342 | if(!m_enabled) | ||
343 | return; | ||
320 | int now = Environment.TickCount & Int32.MaxValue; | 344 | int now = Environment.TickCount & Int32.MaxValue; |
321 | int msElapsed = now - LastWatchdogThreadTick; | 345 | int msElapsed = now - LastWatchdogThreadTick; |
322 | 346 | ||
@@ -332,27 +356,36 @@ namespace OpenSim.Framework.Monitoring | |||
332 | if (callback != null) | 356 | if (callback != null) |
333 | { | 357 | { |
334 | List<ThreadWatchdogInfo> callbackInfos = null; | 358 | List<ThreadWatchdogInfo> callbackInfos = null; |
359 | List<ThreadWatchdogInfo> threadsToRemove = null; | ||
360 | |||
361 | const ThreadState thgone = ThreadState.Stopped; | ||
335 | 362 | ||
336 | lock (m_threads) | 363 | lock (m_threads) |
337 | { | 364 | { |
338 | foreach (ThreadWatchdogInfo threadInfo in m_threads.Values) | 365 | foreach(ThreadWatchdogInfo threadInfo in m_threads.Values) |
339 | { | 366 | { |
340 | if (threadInfo.Thread.ThreadState == ThreadState.Stopped) | 367 | if(!m_enabled) |
368 | return; | ||
369 | if((threadInfo.Thread.ThreadState & thgone) != 0) | ||
341 | { | 370 | { |
342 | RemoveThread(threadInfo.Thread.ManagedThreadId); | 371 | if(threadsToRemove == null) |
372 | threadsToRemove = new List<ThreadWatchdogInfo>(); | ||
343 | 373 | ||
344 | if (callbackInfos == null) | 374 | threadsToRemove.Add(threadInfo); |
375 | /* | ||
376 | if(callbackInfos == null) | ||
345 | callbackInfos = new List<ThreadWatchdogInfo>(); | 377 | callbackInfos = new List<ThreadWatchdogInfo>(); |
346 | 378 | ||
347 | callbackInfos.Add(threadInfo); | 379 | callbackInfos.Add(threadInfo); |
380 | */ | ||
348 | } | 381 | } |
349 | else if (!threadInfo.IsTimedOut && now - threadInfo.LastTick >= threadInfo.Timeout) | 382 | else if(!threadInfo.IsTimedOut && now - threadInfo.LastTick >= threadInfo.Timeout) |
350 | { | 383 | { |
351 | threadInfo.IsTimedOut = true; | 384 | threadInfo.IsTimedOut = true; |
352 | 385 | ||
353 | if (threadInfo.AlarmIfTimeout) | 386 | if(threadInfo.AlarmIfTimeout) |
354 | { | 387 | { |
355 | if (callbackInfos == null) | 388 | if(callbackInfos == null) |
356 | callbackInfos = new List<ThreadWatchdogInfo>(); | 389 | callbackInfos = new List<ThreadWatchdogInfo>(); |
357 | 390 | ||
358 | // Send a copy of the watchdog info to prevent race conditions where the watchdog | 391 | // Send a copy of the watchdog info to prevent race conditions where the watchdog |
@@ -361,9 +394,13 @@ namespace OpenSim.Framework.Monitoring | |||
361 | } | 394 | } |
362 | } | 395 | } |
363 | } | 396 | } |
397 | |||
398 | if(threadsToRemove != null) | ||
399 | foreach(ThreadWatchdogInfo twi in threadsToRemove) | ||
400 | RemoveThread(twi.Thread.ManagedThreadId); | ||
364 | } | 401 | } |
365 | 402 | ||
366 | if (callbackInfos != null) | 403 | if(callbackInfos != null) |
367 | foreach (ThreadWatchdogInfo callbackInfo in callbackInfos) | 404 | foreach (ThreadWatchdogInfo callbackInfo in callbackInfos) |
368 | callback(callbackInfo); | 405 | callback(callbackInfo); |
369 | } | 406 | } |
@@ -377,4 +414,4 @@ namespace OpenSim.Framework.Monitoring | |||
377 | m_watchdogTimer.Start(); | 414 | m_watchdogTimer.Start(); |
378 | } | 415 | } |
379 | } | 416 | } |
380 | } \ No newline at end of file | 417 | } |
diff --git a/OpenSim/Framework/Monitoring/WorkManager.cs b/OpenSim/Framework/Monitoring/WorkManager.cs index d1a74ce..5d9b185 100644 --- a/OpenSim/Framework/Monitoring/WorkManager.cs +++ b/OpenSim/Framework/Monitoring/WorkManager.cs | |||
@@ -36,16 +36,16 @@ namespace OpenSim.Framework.Monitoring | |||
36 | /// Manages various work items in the simulator. | 36 | /// Manages various work items in the simulator. |
37 | /// </summary> | 37 | /// </summary> |
38 | /// <remarks> | 38 | /// <remarks> |
39 | /// Currently, here work can be started | 39 | /// Currently, here work can be started |
40 | /// * As a long-running and monitored thread. | 40 | /// * As a long-running and monitored thread. |
41 | /// * In a thread that will never timeout but where the job is expected to eventually complete. | 41 | /// * In a thread that will never timeout but where the job is expected to eventually complete. |
42 | /// * In a threadpool thread that will timeout if it takes a very long time to complete (> 10 mins). | 42 | /// * In a threadpool thread that will timeout if it takes a very long time to complete (> 10 mins). |
43 | /// * As a job which will be run in a single-threaded job engine. Such jobs must not incorporate delays (sleeps, | 43 | /// * As a job which will be run in a single-threaded job engine. Such jobs must not incorporate delays (sleeps, |
44 | /// network waits, etc.). | 44 | /// network waits, etc.). |
45 | /// | 45 | /// |
46 | /// This is an evolving approach to better manage the work that OpenSimulator is asked to do from a very diverse | 46 | /// This is an evolving approach to better manage the work that OpenSimulator is asked to do from a very diverse |
47 | /// range of sources (client actions, incoming network, outgoing network calls, etc.). | 47 | /// range of sources (client actions, incoming network, outgoing network calls, etc.). |
48 | /// | 48 | /// |
49 | /// Util.FireAndForget is still available to insert jobs in the threadpool, though this is equivalent to | 49 | /// Util.FireAndForget is still available to insert jobs in the threadpool, though this is equivalent to |
50 | /// WorkManager.RunInThreadPool(). | 50 | /// WorkManager.RunInThreadPool(). |
51 | /// </remarks> | 51 | /// </remarks> |
@@ -57,7 +57,7 @@ namespace OpenSim.Framework.Monitoring | |||
57 | 57 | ||
58 | static WorkManager() | 58 | static WorkManager() |
59 | { | 59 | { |
60 | JobEngine = new JobEngine("Non-blocking non-critical job engine", "JOB ENGINE"); | 60 | JobEngine = new JobEngine("Non-blocking non-critical job engine", "JOB ENGINE", 30000); |
61 | 61 | ||
62 | StatsManager.RegisterStat( | 62 | StatsManager.RegisterStat( |
63 | new Stat( | 63 | new Stat( |
@@ -82,6 +82,12 @@ namespace OpenSim.Framework.Monitoring | |||
82 | HandleControlCommand); | 82 | HandleControlCommand); |
83 | } | 83 | } |
84 | 84 | ||
85 | public static void Stop() | ||
86 | { | ||
87 | JobEngine.Stop(); | ||
88 | Watchdog.Stop(); | ||
89 | } | ||
90 | |||
85 | /// <summary> | 91 | /// <summary> |
86 | /// Start a new long-lived thread. | 92 | /// Start a new long-lived thread. |
87 | /// </summary> | 93 | /// </summary> |
@@ -121,6 +127,7 @@ namespace OpenSim.Framework.Monitoring | |||
121 | Thread thread = new Thread(start); | 127 | Thread thread = new Thread(start); |
122 | thread.Priority = priority; | 128 | thread.Priority = priority; |
123 | thread.IsBackground = isBackground; | 129 | thread.IsBackground = isBackground; |
130 | thread.Name = name; | ||
124 | 131 | ||
125 | Watchdog.ThreadWatchdogInfo twi | 132 | Watchdog.ThreadWatchdogInfo twi |
126 | = new Watchdog.ThreadWatchdogInfo(thread, timeout, name) | 133 | = new Watchdog.ThreadWatchdogInfo(thread, timeout, name) |
@@ -129,7 +136,6 @@ namespace OpenSim.Framework.Monitoring | |||
129 | Watchdog.AddThread(twi, name, log:log); | 136 | Watchdog.AddThread(twi, name, log:log); |
130 | 137 | ||
131 | thread.Start(); | 138 | thread.Start(); |
132 | thread.Name = name; | ||
133 | 139 | ||
134 | return thread; | 140 | return thread; |
135 | } | 141 | } |
@@ -143,7 +149,7 @@ namespace OpenSim.Framework.Monitoring | |||
143 | /// <param name="name">Name of the thread</param> | 149 | /// <param name="name">Name of the thread</param> |
144 | public static void RunInThread(WaitCallback callback, object obj, string name, bool log = false) | 150 | public static void RunInThread(WaitCallback callback, object obj, string name, bool log = false) |
145 | { | 151 | { |
146 | if (Util.FireAndForgetMethod == FireAndForgetMethod.RegressionTest) | 152 | if (Util.FireAndForgetMethod == FireAndForgetMethod.RegressionTest) |
147 | { | 153 | { |
148 | Culture.SetCurrentCulture(); | 154 | Culture.SetCurrentCulture(); |
149 | callback(obj); | 155 | callback(obj); |
@@ -168,7 +174,7 @@ namespace OpenSim.Framework.Monitoring | |||
168 | } | 174 | } |
169 | 175 | ||
170 | /// <summary> | 176 | /// <summary> |
171 | /// Run the callback via a threadpool thread. | 177 | /// Run the callback via a threadpool thread. |
172 | /// </summary> | 178 | /// </summary> |
173 | /// <remarks> | 179 | /// <remarks> |
174 | /// Such jobs may run after some delay but must always complete. | 180 | /// Such jobs may run after some delay but must always complete. |
@@ -176,9 +182,9 @@ namespace OpenSim.Framework.Monitoring | |||
176 | /// <param name="callback"></param> | 182 | /// <param name="callback"></param> |
177 | /// <param name="obj"></param> | 183 | /// <param name="obj"></param> |
178 | /// <param name="name">The name of the job. This is used in monitoring and debugging.</param> | 184 | /// <param name="name">The name of the job. This is used in monitoring and debugging.</param> |
179 | public static void RunInThreadPool(System.Threading.WaitCallback callback, object obj, string name) | 185 | public static void RunInThreadPool(System.Threading.WaitCallback callback, object obj, string name, bool timeout = true) |
180 | { | 186 | { |
181 | Util.FireAndForget(callback, obj, name); | 187 | Util.FireAndForget(callback, obj, name, timeout); |
182 | } | 188 | } |
183 | 189 | ||
184 | /// <summary> | 190 | /// <summary> |
@@ -187,17 +193,17 @@ namespace OpenSim.Framework.Monitoring | |||
187 | /// <remarks> | 193 | /// <remarks> |
188 | /// This differs from direct scheduling (e.g. Util.FireAndForget) in that a job can be run in the job | 194 | /// This differs from direct scheduling (e.g. Util.FireAndForget) in that a job can be run in the job |
189 | /// engine if it is running, where all jobs are currently performed in sequence on a single thread. This is | 195 | /// engine if it is running, where all jobs are currently performed in sequence on a single thread. This is |
190 | /// to prevent observed overload and server freeze problems when there are hundreds of connections which all attempt to | 196 | /// to prevent observed overload and server freeze problems when there are hundreds of connections which all attempt to |
191 | /// perform work at once (e.g. in conference situations). With lower numbers of connections, the small | 197 | /// perform work at once (e.g. in conference situations). With lower numbers of connections, the small |
192 | /// delay in performing jobs in sequence rather than concurrently has not been notiecable in testing, though a future more | 198 | /// delay in performing jobs in sequence rather than concurrently has not been notiecable in testing, though a future more |
193 | /// sophisticated implementation could perform jobs concurrently when the server is under low load. | 199 | /// sophisticated implementation could perform jobs concurrently when the server is under low load. |
194 | /// | 200 | /// |
195 | /// However, be advised that some callers of this function rely on all jobs being performed in sequence if any | 201 | /// However, be advised that some callers of this function rely on all jobs being performed in sequence if any |
196 | /// jobs are performed in sequence (i.e. if jobengine is active or not). Therefore, expanding the jobengine | 202 | /// jobs are performed in sequence (i.e. if jobengine is active or not). Therefore, expanding the jobengine |
197 | /// beyond a single thread will require considerable thought. | 203 | /// beyond a single thread will require considerable thought. |
198 | /// | 204 | /// |
199 | /// Also, any jobs submitted must be guaranteed to complete within a reasonable timeframe (e.g. they cannot | 205 | /// Also, any jobs submitted must be guaranteed to complete within a reasonable timeframe (e.g. they cannot |
200 | /// incorporate a network delay with a long timeout). At the moment, work that could suffer such issues | 206 | /// incorporate a network delay with a long timeout). At the moment, work that could suffer such issues |
201 | /// should still be run directly with RunInThread(), Util.FireAndForget(), etc. This is another area where | 207 | /// should still be run directly with RunInThread(), Util.FireAndForget(), etc. This is another area where |
202 | /// the job engine could be improved and so CPU utilization improved by better management of concurrency within | 208 | /// the job engine could be improved and so CPU utilization improved by better management of concurrency within |
203 | /// OpenSimulator. | 209 | /// OpenSimulator. |
@@ -211,10 +217,10 @@ namespace OpenSim.Framework.Monitoring | |||
211 | /// <param name="log">If set to true then extra logging is performed.</param> | 217 | /// <param name="log">If set to true then extra logging is performed.</param> |
212 | public static void RunJob( | 218 | public static void RunJob( |
213 | string jobType, WaitCallback callback, object obj, string name, | 219 | string jobType, WaitCallback callback, object obj, string name, |
214 | bool canRunInThisThread = false, bool mustNotTimeout = false, | 220 | bool canRunInThisThread = false, bool mustNotTimeout = false, |
215 | bool log = false) | 221 | bool log = false) |
216 | { | 222 | { |
217 | if (Util.FireAndForgetMethod == FireAndForgetMethod.RegressionTest) | 223 | if (Util.FireAndForgetMethod == FireAndForgetMethod.RegressionTest) |
218 | { | 224 | { |
219 | Culture.SetCurrentCulture(); | 225 | Culture.SetCurrentCulture(); |
220 | callback(obj); | 226 | callback(obj); |
@@ -225,10 +231,8 @@ namespace OpenSim.Framework.Monitoring | |||
225 | JobEngine.QueueJob(name, () => callback(obj)); | 231 | JobEngine.QueueJob(name, () => callback(obj)); |
226 | else if (canRunInThisThread) | 232 | else if (canRunInThisThread) |
227 | callback(obj); | 233 | callback(obj); |
228 | else if (mustNotTimeout) | ||
229 | RunInThread(callback, obj, name, log); | ||
230 | else | 234 | else |
231 | Util.FireAndForget(callback, obj, name); | 235 | Util.FireAndForget(callback, obj, name, !mustNotTimeout); |
232 | } | 236 | } |
233 | 237 | ||
234 | private static void HandleControlCommand(string module, string[] args) | 238 | private static void HandleControlCommand(string module, string[] args) |
@@ -272,16 +276,16 @@ namespace OpenSim.Framework.Monitoring | |||
272 | MainConsole.Instance.Output("Usage: debug jobengine log <level>"); | 276 | MainConsole.Instance.Output("Usage: debug jobengine log <level>"); |
273 | return; | 277 | return; |
274 | } | 278 | } |
275 | 279 | ||
276 | // int logLevel; | 280 | // int logLevel; |
277 | int logLevel = int.Parse(args[3]); | 281 | int logLevel = int.Parse(args[3]); |
278 | // if (ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out logLevel)) | 282 | // if (ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out logLevel)) |
279 | // { | 283 | // { |
280 | JobEngine.LogLevel = logLevel; | 284 | JobEngine.LogLevel = logLevel; |
281 | MainConsole.Instance.OutputFormat("Set debug log level to {0}", JobEngine.LogLevel); | 285 | MainConsole.Instance.OutputFormat("Set debug log level to {0}", JobEngine.LogLevel); |
282 | // } | 286 | // } |
283 | } | 287 | } |
284 | else | 288 | else |
285 | { | 289 | { |
286 | MainConsole.Instance.OutputFormat("Unrecognized job engine subcommand {0}", subCommand); | 290 | MainConsole.Instance.OutputFormat("Unrecognized job engine subcommand {0}", subCommand); |
287 | } | 291 | } |