OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
ChecksManager.cs
Go to the documentation of this file.
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 
28 using System;
29 using System.Collections.Generic;
30 using System.Linq;
31 using System.Reflection;
32 using System.Text;
33 using log4net;
34 
35 namespace OpenSim.Framework.Monitoring
36 {
40  public static class ChecksManager
41  {
42  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 
44  // Subcommand used to list other stats.
45  public const string ListSubCommand = "list";
46 
47  // All subcommands
48  public static HashSet<string> SubCommands = new HashSet<string> { ListSubCommand };
49 
56  public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Check>>> RegisteredChecks
57  = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Check>>>();
58 
59  public static void RegisterConsoleCommands(ICommandConsole console)
60  {
61  console.Commands.AddCommand(
62  "General",
63  false,
64  "show checks",
65  "show checks",
66  "Show checks configured for this server",
67  "If no argument is specified then info on all checks will be shown.\n"
68  + "'list' argument will show check categories.\n"
69  + "THIS FACILITY IS EXPERIMENTAL",
70  HandleShowchecksCommand);
71  }
72 
73  public static void HandleShowchecksCommand(string module, string[] cmd)
74  {
75  ICommandConsole con = MainConsole.Instance;
76 
77  if (cmd.Length > 2)
78  {
79  foreach (string name in cmd.Skip(2))
80  {
81  string[] components = name.Split('.');
82 
83  string categoryName = components[0];
84 // string containerName = components.Length > 1 ? components[1] : null;
85 
86  if (categoryName == ListSubCommand)
87  {
88  con.Output("check categories available are:");
89 
90  foreach (string category in RegisteredChecks.Keys)
91  con.OutputFormat(" {0}", category);
92  }
93 // else
94 // {
95 // SortedDictionary<string, SortedDictionary<string, Check>> category;
96 // if (!Registeredchecks.TryGetValue(categoryName, out category))
97 // {
98 // con.OutputFormat("No such category as {0}", categoryName);
99 // }
100 // else
101 // {
102 // if (String.IsNullOrEmpty(containerName))
103 // {
104 // OutputConfiguredToConsole(con, category);
105 // }
106 // else
107 // {
108 // SortedDictionary<string, Check> container;
109 // if (category.TryGetValue(containerName, out container))
110 // {
111 // OutputContainerChecksToConsole(con, container);
112 // }
113 // else
114 // {
115 // con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
116 // }
117 // }
118 // }
119 // }
120  }
121  }
122  else
123  {
124  OutputAllChecksToConsole(con);
125  }
126  }
127 
133  public static bool RegisterCheck(Check check)
134  {
135  SortedDictionary<string, SortedDictionary<string, Check>> category = null, newCategory;
136  SortedDictionary<string, Check> container = null, newContainer;
137 
138  lock (RegisteredChecks)
139  {
140  // Check name is not unique across category/container/shortname key.
141  // XXX: For now just return false. This is to avoid problems in regression tests where all tests
142  // in a class are run in the same instance of the VM.
143  if (TryGetCheckParents(check, out category, out container))
144  return false;
145 
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
148  // common operation after startup.
149  if (container != null)
150  newContainer = new SortedDictionary<string, Check>(container);
151  else
152  newContainer = new SortedDictionary<string, Check>();
153 
154  if (category != null)
155  newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>(category);
156  else
157  newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>();
158 
159  newContainer[check.ShortName] = check;
160  newCategory[check.Container] = newContainer;
161  RegisteredChecks[check.Category] = newCategory;
162  }
163 
164  return true;
165  }
166 
172  public static bool DeregisterCheck(Check check)
173  {
174  SortedDictionary<string, SortedDictionary<string, Check>> category = null, newCategory;
175  SortedDictionary<string, Check> container = null, newContainer;
176 
177  lock (RegisteredChecks)
178  {
179  if (!TryGetCheckParents(check, out category, out container))
180  return false;
181 
182  newContainer = new SortedDictionary<string, Check>(container);
183  newContainer.Remove(check.ShortName);
184 
185  newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>(category);
186  newCategory.Remove(check.Container);
187 
188  newCategory[check.Container] = newContainer;
189  RegisteredChecks[check.Category] = newCategory;
190 
191  return true;
192  }
193  }
194 
195  public static bool TryGetCheckParents(
196  Check check,
197  out SortedDictionary<string, SortedDictionary<string, Check>> category,
198  out SortedDictionary<string, Check> container)
199  {
200  category = null;
201  container = null;
202 
203  lock (RegisteredChecks)
204  {
205  if (RegisteredChecks.TryGetValue(check.Category, out category))
206  {
207  if (category.TryGetValue(check.Container, out container))
208  {
209  if (container.ContainsKey(check.ShortName))
210  return true;
211  }
212  }
213  }
214 
215  return false;
216  }
217 
218  public static void CheckChecks()
219  {
220  lock (RegisteredChecks)
221  {
222  foreach (SortedDictionary<string, SortedDictionary<string, Check>> category in RegisteredChecks.Values)
223  {
224  foreach (SortedDictionary<string, Check> container in category.Values)
225  {
226  foreach (Check check in container.Values)
227  {
228  if (!check.CheckIt())
229  m_log.WarnFormat(
230  "[CHECKS MANAGER]: Check {0}.{1}.{2} failed with message {3}", check.Category, check.Container, check.ShortName, check.LastFailureMessage);
231  }
232  }
233  }
234  }
235  }
236 
237  private static void OutputAllChecksToConsole(ICommandConsole con)
238  {
239  foreach (var category in RegisteredChecks.Values)
240  {
241  OutputCategoryChecksToConsole(con, category);
242  }
243  }
244 
245  private static void OutputCategoryChecksToConsole(
246  ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Check>> category)
247  {
248  foreach (var container in category.Values)
249  {
250  OutputContainerChecksToConsole(con, container);
251  }
252  }
253 
254  private static void OutputContainerChecksToConsole(ICommandConsole con, SortedDictionary<string, Check> container)
255  {
256  foreach (Check check in container.Values)
257  {
258  con.Output(check.ToConsoleString());
259  }
260  }
261  }
262 }