29 using System.Collections.Generic;
31 using System.Reflection;
33 using System.Text.RegularExpressions;
36 using OpenSim.Region.DataSnapshot.Interfaces;
37 using OpenSim.Region.Framework.Scenes;
39 namespace OpenSim.
Region.DataSnapshot
44 private String m_directory =
"unyuu";
45 private Dictionary<Scene, bool> m_scenes = null;
46 private List<IDataSnapshotProvider> m_providers = null;
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 private Dictionary<String, String> m_gridinfo = null;
49 private bool m_cacheEnabled =
true;
50 private string m_listener_port =
"9000";
51 private string m_hostname =
"127.0.0.1";
54 public SnapshotStore(
string directory, Dictionary<String, String> gridinfo,
string port,
string hostname) {
55 m_directory = directory;
56 m_scenes =
new Dictionary<Scene, bool>();
57 m_providers =
new List<IDataSnapshotProvider>();
58 m_gridinfo = gridinfo;
59 m_listener_port = port;
60 m_hostname = hostname;
62 if (Directory.Exists(m_directory))
64 m_log.Info(
"[DATASNAPSHOT]: Response and fragment cache directory already exists.");
69 m_log.Info(
"[DATASNAPSHOT]: Creating directory " + m_directory);
72 Directory.CreateDirectory(m_directory);
76 m_log.Error(
"[DATASNAPSHOT]: Failed to create directory " + m_directory, e);
79 m_cacheEnabled =
false;
80 m_log.Error(
"[DATASNAPSHOT]: Could not create directory, response cache has been disabled.");
86 m_scenes[scene] =
true;
89 #region Fragment storage
94 if (provider.
Stale || !m_cacheEnabled)
96 data = provider.RequestSnapshotData(factory);
104 using (XmlTextWriter snapXWriter =
new XmlTextWriter(path, Encoding.Default))
106 snapXWriter.Formatting = Formatting.Indented;
107 snapXWriter.WriteStartDocument();
108 data.WriteTo(snapXWriter);
109 snapXWriter.WriteEndDocument();
114 m_log.WarnFormat(
"[DATASNAPSHOT]: Exception on writing to file {0}: {1}", path, e.Message);
120 provider.Stale =
false;
121 m_scenes[provider.GetParentScene] =
true;
123 m_log.Debug(
"[DATASNAPSHOT]: Generated fragment response for provider type " + provider.Name);
129 XmlDocument fragDocument =
new XmlDocument();
130 fragDocument.PreserveWhitespace =
true;
131 fragDocument.Load(path);
132 foreach (XmlNode node
in fragDocument)
134 data = factory.ImportNode(node,
true);
137 m_log.Debug(
"[DATASNAPSHOT]: Retrieved fragment response for provider type " + provider.Name);
144 #region Response storage
147 m_log.Debug(
"[DATASNAPSHOT]: Data requested for scene " + scene.RegionInfo.RegionName);
149 if (!m_scenes.ContainsKey(scene)) {
150 m_scenes.Add(scene,
true);
153 XmlNode regionElement = null;
155 if (!m_scenes[scene])
157 m_log.Debug(
"[DATASNAPSHOT]: Attempting to retrieve snapshot from cache.");
159 String path = DataFileNameScene(scene);
161 XmlDocument fragDocument =
new XmlDocument();
162 fragDocument.PreserveWhitespace =
true;
164 fragDocument.Load(path);
166 foreach (XmlNode node
in fragDocument)
168 regionElement = factory.ImportNode(node,
true);
171 m_log.Debug(
"[DATASNAPSHOT]: Obtained snapshot from cache for " + scene.RegionInfo.RegionName);
175 m_log.Debug(
"[DATASNAPSHOT]: Attempting to generate snapshot.");
177 regionElement = MakeRegionNode(scene, factory);
179 regionElement.AppendChild(GetGridSnapshotData(factory));
180 XmlNode regionData = factory.CreateNode(XmlNodeType.Element,
"data",
"");
186 regionData.AppendChild(GetFragment(dataprovider, factory));
190 regionElement.AppendChild(regionData);
192 factory.AppendChild(regionElement);
195 String path = DataFileNameScene(scene);
199 using (XmlTextWriter snapXWriter =
new XmlTextWriter(path, Encoding.Default))
201 snapXWriter.Formatting = Formatting.Indented;
202 snapXWriter.WriteStartDocument();
203 regionElement.WriteTo(snapXWriter);
204 snapXWriter.WriteEndDocument();
209 m_log.WarnFormat(
"[DATASNAPSHOT]: Exception on writing to file {0}: {1}", path, e.Message);
212 m_scenes[scene] =
false;
214 m_log.Debug(
"[DATASNAPSHOT]: Generated new snapshot for " + scene.RegionInfo.RegionName);
217 return regionElement;
223 private string DataFileNameFragment(
Scene scene, String fragmentName)
225 return Path.Combine(m_directory, Path.ChangeExtension(Sanitize(scene.
RegionInfo.RegionName +
"_" + fragmentName),
"xml"));
228 private string DataFileNameScene(
Scene scene)
230 return Path.Combine(m_directory, Path.ChangeExtension(Sanitize(scene.
RegionInfo.RegionName),
"xml"));
234 private static string Sanitize(
string name)
236 string invalidChars = Regex.Escape(
new string(Path.GetInvalidFileNameChars()));
237 string invalidReStr = string.Format(
@"[{0}]", invalidChars);
238 string newname = Regex.Replace(name, invalidReStr,
"_");
239 return newname.Replace(
'.',
'_');
242 private XmlNode MakeRegionNode(
Scene scene, XmlDocument basedoc)
244 XmlNode docElement = basedoc.CreateNode(XmlNodeType.Element,
"region",
"");
246 XmlAttribute attr = basedoc.CreateAttribute(
"category");
247 attr.Value = GetRegionCategory(scene);
248 docElement.Attributes.Append(attr);
250 attr = basedoc.CreateAttribute(
"entities");
251 attr.Value = scene.Entities.Count.ToString();
252 docElement.Attributes.Append(attr);
259 XmlNode infoblock = basedoc.CreateNode(XmlNodeType.Element,
"info",
"");
261 XmlNode infopiece = basedoc.CreateNode(XmlNodeType.Element,
"uuid",
"");
262 infopiece.InnerText = scene.RegionInfo.RegionID.ToString();
263 infoblock.AppendChild(infopiece);
265 infopiece = basedoc.CreateNode(XmlNodeType.Element,
"url",
"");
266 infopiece.InnerText =
"http://" + m_hostname +
":" + m_listener_port;
267 infoblock.AppendChild(infopiece);
269 infopiece = basedoc.CreateNode(XmlNodeType.Element,
"name",
"");
270 infopiece.InnerText = scene.RegionInfo.RegionName;
271 infoblock.AppendChild(infopiece);
273 infopiece = basedoc.CreateNode(XmlNodeType.Element,
"handle",
"");
274 infopiece.InnerText = scene.RegionInfo.RegionHandle.ToString();
275 infoblock.AppendChild(infopiece);
277 docElement.AppendChild(infoblock);
279 m_log.Debug(
"[DATASNAPSHOT]: Generated region node");
285 if (scene.
RegionInfo.RegionSettings.Maturity == 0)
288 if (scene.
RegionInfo.RegionSettings.Maturity == 1)
291 if (scene.
RegionInfo.RegionSettings.Maturity == 2)
297 private XmlNode GetGridSnapshotData(XmlDocument factory)
299 XmlNode griddata = factory.CreateNode(XmlNodeType.Element,
"grid",
"");
301 foreach (KeyValuePair<String, String> GridData
in m_gridinfo)
304 XmlNode childnode = factory.CreateNode(XmlNodeType.Element, GridData.Key,
"");
305 childnode.InnerText = GridData.Value;
306 griddata.AppendChild(childnode);
309 m_log.Debug(
"[DATASNAPSHOT]: Got grid snapshot data");
315 #region Manage internal collections
318 m_scenes.Add(newScene,
true);
323 m_scenes.Remove(deadScene);
328 m_providers.Add(newProvider);
333 m_providers.Remove(deadProvider);
void AddScene(Scene newScene)
XmlNode GetFragment(IDataSnapshotProvider provider, XmlDocument factory)
void AddProvider(IDataSnapshotProvider newProvider)
SnapshotStore(string directory, Dictionary< String, String > gridinfo, string port, string hostname)
void ForceSceneStale(Scene scene)
void RemoveProvider(IDataSnapshotProvider deadProvider)
XmlNode GetScene(Scene scene, XmlDocument factory)
virtual RegionInfo RegionInfo
void RemoveScene(Scene deadScene)