diff options
Diffstat (limited to 'OpenSim/Region/DataSnapshot/DataSnapshotManager.cs')
-rw-r--r-- | OpenSim/Region/DataSnapshot/DataSnapshotManager.cs | 524 |
1 files changed, 524 insertions, 0 deletions
diff --git a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs new file mode 100644 index 0000000..1831f0a --- /dev/null +++ b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs | |||
@@ -0,0 +1,524 @@ | |||
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 OpenSim 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 | |||
29 | using System; | ||
30 | using System.Collections.Generic; | ||
31 | using System.Reflection; | ||
32 | using System.Xml; | ||
33 | using System.IO; | ||
34 | using System.Text; | ||
35 | using System.Timers; | ||
36 | using OpenSim.Framework; | ||
37 | using OpenSim.Framework.Communications; | ||
38 | using OpenSim.Region.Environment.Interfaces; | ||
39 | using OpenSim.Region.Environment.Scenes; | ||
40 | using Nini.Config; | ||
41 | using libsecondlife; | ||
42 | using libsecondlife.Packets; | ||
43 | |||
44 | namespace OpenSim.Region.DataSnapshot | ||
45 | { | ||
46 | public class DataSnapshotManager : IRegionModule | ||
47 | { | ||
48 | #region Class members | ||
49 | private List<Scene> m_scenes = new List<Scene>(); | ||
50 | private log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
51 | private bool m_enabled = false; | ||
52 | private bool m_configLoaded = false; | ||
53 | internal object m_syncInit = new object(); | ||
54 | private DataRequestHandler m_requests = null; | ||
55 | private Dictionary<Scene, List<IDataSnapshotProvider>> m_dataproviders = new Dictionary<Scene, List<IDataSnapshotProvider>>(); | ||
56 | private Dictionary<String, String> m_gridinfo = new Dictionary<String, String>(); | ||
57 | //private int m_oldestSnapshot = 0; | ||
58 | private int m_maxSnapshots = 500; | ||
59 | private int m_lastSnapshot = 0; | ||
60 | private string m_snapsDir = "DataSnapshot"; | ||
61 | private string m_dataServices = "noservices"; | ||
62 | private string m_listener_port = "9000"; //TODO: Set default port over 9000 | ||
63 | private string m_hostname = "127.0.0.1"; | ||
64 | private Timer m_periodic = null; | ||
65 | private int m_period = 60; // in seconds | ||
66 | private List<String> m_disabledModules = new List<String>(); | ||
67 | #endregion | ||
68 | |||
69 | #region IRegionModule | ||
70 | public void Close() | ||
71 | { | ||
72 | |||
73 | } | ||
74 | |||
75 | public void Initialise(Scene scene, Nini.Config.IConfigSource config) | ||
76 | { | ||
77 | if (!m_scenes.Contains(scene)) | ||
78 | m_scenes.Add(scene); | ||
79 | |||
80 | if (!m_configLoaded) { | ||
81 | m_configLoaded = true; | ||
82 | m_log.Info("[DATASNAPSHOT]: Loading configuration"); | ||
83 | //Read from the config for options | ||
84 | lock (m_syncInit) { | ||
85 | try { | ||
86 | m_enabled = config.Configs["DataSnapshot"].GetBoolean("index_sims", m_enabled); | ||
87 | if (config.Configs["Startup"].GetBoolean("gridmode", true)) | ||
88 | { | ||
89 | m_gridinfo.Add("gridserverURL", config.Configs["Network"].GetString("grid_server_url", "harbl")); | ||
90 | m_gridinfo.Add("userserverURL", config.Configs["Network"].GetString("user_server_url", "harbl")); | ||
91 | m_gridinfo.Add("assetserverURL", config.Configs["Network"].GetString("asset_server_url", "harbl")); | ||
92 | } | ||
93 | else | ||
94 | { | ||
95 | //Non gridmode stuff | ||
96 | } | ||
97 | |||
98 | m_gridinfo.Add("Name", config.Configs["DataSnapshot"].GetString("gridname", "harbl")); | ||
99 | m_maxSnapshots = config.Configs["DataSnapshot"].GetInt("max_snapshots", m_maxSnapshots); | ||
100 | m_period = config.Configs["DataSnapshot"].GetInt("default_snapshot_period", m_period); | ||
101 | m_snapsDir = config.Configs["DataSnapshot"].GetString("snapshot_cache_directory", m_snapsDir); | ||
102 | m_dataServices = config.Configs["DataSnapshot"].GetString("data_services", m_dataServices); | ||
103 | m_listener_port = config.Configs["Network"].GetString("http_listener_port", m_listener_port); | ||
104 | //BUG: Naming a search data module "DESUDESUDESU" will cause it to not get loaded by default. | ||
105 | //RESOLUTION: Wontfix, there are no Suiseiseki-loving developers | ||
106 | String[] annoying_string_array = config.Configs["DataSnapshot"].GetString("disable_modules", "DESUDESUDESU").Split(".".ToCharArray()); | ||
107 | foreach (String bloody_wanker in annoying_string_array) { | ||
108 | m_disabledModules.Add(bloody_wanker); | ||
109 | } | ||
110 | |||
111 | } catch (Exception) { | ||
112 | m_log.Info("[DATASNAPSHOT]: Could not load configuration. DataSnapshot will be disabled."); | ||
113 | m_enabled = false; | ||
114 | return; | ||
115 | } | ||
116 | |||
117 | } | ||
118 | } | ||
119 | if (Directory.Exists(m_snapsDir)) | ||
120 | { | ||
121 | m_log.Info("[DATASNAPSHOT] DataSnapshot directory already exists."); | ||
122 | } | ||
123 | else | ||
124 | { | ||
125 | // Try to create the directory. | ||
126 | m_log.Info("[DATASNAPSHOT] Creating " + m_snapsDir + " directory."); | ||
127 | try | ||
128 | { | ||
129 | Directory.CreateDirectory(m_snapsDir); | ||
130 | } | ||
131 | catch (Exception) | ||
132 | { | ||
133 | m_log.Error("[DATASNAPSHOT] Failed to create " + m_snapsDir + " directory."); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | |||
138 | if (m_enabled) | ||
139 | { | ||
140 | m_log.Info("[DATASNAPSHOT]: Scene added to module."); | ||
141 | } | ||
142 | else | ||
143 | { | ||
144 | m_log.Warn("[DATASNAPSHOT]: Data snapshot disabled, not adding scene to module (or anything else)."); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | public bool IsSharedModule | ||
149 | { | ||
150 | get { return true; } | ||
151 | } | ||
152 | |||
153 | public string Name | ||
154 | { | ||
155 | get { return "External Data Generator"; } | ||
156 | } | ||
157 | |||
158 | public void PostInitialise() | ||
159 | { | ||
160 | if (m_enabled) | ||
161 | { | ||
162 | //Right now, only load ISearchData objects in the current assembly. | ||
163 | //Eventually allow it to load ISearchData objects from all assemblies. | ||
164 | Assembly currentasm = Assembly.GetExecutingAssembly(); | ||
165 | |||
166 | //Stolen from ModuleLoader.cs | ||
167 | foreach (Type pluginType in currentasm.GetTypes()) | ||
168 | { | ||
169 | if (pluginType.IsPublic) | ||
170 | { | ||
171 | if (!pluginType.IsAbstract) | ||
172 | { | ||
173 | if (pluginType.GetInterface("IDataSnapshotProvider") != null) | ||
174 | { | ||
175 | foreach (Scene scene in m_scenes) | ||
176 | { | ||
177 | IDataSnapshotProvider module = (IDataSnapshotProvider)Activator.CreateInstance(pluginType); | ||
178 | module.Initialize(scene, this); | ||
179 | //module.PrepareData(); | ||
180 | List<IDataSnapshotProvider> providerlist = null; | ||
181 | m_dataproviders.TryGetValue(scene, out providerlist); | ||
182 | if (providerlist == null) | ||
183 | { | ||
184 | providerlist = new List<IDataSnapshotProvider>(); | ||
185 | m_dataproviders.Add(scene, providerlist); | ||
186 | } | ||
187 | providerlist.Add(module); | ||
188 | |||
189 | } | ||
190 | m_log.Info("[DATASNAPSHOT]: Added new data provider type: " + pluginType.Name); | ||
191 | } | ||
192 | } | ||
193 | } | ||
194 | } | ||
195 | |||
196 | //Hand it the first scene, assuming that all scenes have the same BaseHTTPServer | ||
197 | m_requests = new DataRequestHandler(m_scenes[0], this); | ||
198 | |||
199 | //Create timer | ||
200 | m_periodic = new Timer(); | ||
201 | m_periodic.Interval = m_period * 1000; | ||
202 | m_periodic.Elapsed += SnapshotTimerCallback; | ||
203 | m_periodic.Enabled = true; | ||
204 | |||
205 | m_hostname = m_scenes[0].RegionInfo.ExternalHostName; | ||
206 | |||
207 | MakeNewSnapshot(); //Make the initial snapshot | ||
208 | |||
209 | if (m_dataServices != "noservices") | ||
210 | NotifyDataServices(m_dataServices); | ||
211 | } | ||
212 | } | ||
213 | #endregion | ||
214 | |||
215 | #region Associated helper functions | ||
216 | |||
217 | string DataFileName(Scene scene) | ||
218 | { | ||
219 | return Path.Combine(m_snapsDir, Path.ChangeExtension(scene.RegionInfo.RegionName, "xml")); | ||
220 | //return (m_snapsDir + Path.DirectorySeparatorChar + scene.RegionInfo.RegionName + ".xml"); | ||
221 | } | ||
222 | |||
223 | Scene SceneForName(string name) | ||
224 | { | ||
225 | foreach (Scene scene in m_scenes) | ||
226 | if (scene.RegionInfo.RegionName == name) | ||
227 | return scene; | ||
228 | |||
229 | return null; | ||
230 | } | ||
231 | |||
232 | #endregion | ||
233 | |||
234 | #region [Private] XML snapshot generator | ||
235 | |||
236 | private XmlDocument Snapshot(Scene scene) | ||
237 | { | ||
238 | XmlDocument basedoc = new XmlDocument(); | ||
239 | XmlNode regionElement = MakeRegionNode(scene, basedoc); | ||
240 | |||
241 | regionElement.AppendChild(GetGridSnapshotData(basedoc)); | ||
242 | XmlNode regionData = basedoc.CreateNode(XmlNodeType.Element, "data", ""); | ||
243 | |||
244 | foreach (KeyValuePair<Scene, List<IDataSnapshotProvider>> dataprovider in m_dataproviders) | ||
245 | { | ||
246 | if (dataprovider.Key == scene) | ||
247 | { | ||
248 | foreach (IDataSnapshotProvider provider in dataprovider.Value) | ||
249 | { | ||
250 | XmlNode data = provider.RequestSnapshotData(basedoc); | ||
251 | regionData.AppendChild(data); | ||
252 | } | ||
253 | } | ||
254 | } | ||
255 | |||
256 | regionElement.AppendChild(regionData); | ||
257 | |||
258 | basedoc.AppendChild(regionElement); | ||
259 | |||
260 | return basedoc; | ||
261 | } | ||
262 | |||
263 | private XmlNode MakeRegionNode(Scene scene, XmlDocument basedoc) | ||
264 | { | ||
265 | XmlNode docElement = basedoc.CreateNode(XmlNodeType.Element, "region", ""); | ||
266 | |||
267 | XmlAttribute attr = basedoc.CreateAttribute("category"); | ||
268 | attr.Value = GetRegionCategory(scene); | ||
269 | docElement.Attributes.Append(attr); | ||
270 | |||
271 | attr = basedoc.CreateAttribute("entities"); | ||
272 | attr.Value = scene.Entities.Count.ToString(); | ||
273 | docElement.Attributes.Append(attr); | ||
274 | |||
275 | //attr = basedoc.CreateAttribute("parcels"); | ||
276 | //attr.Value = scene.LandManager.landList.Count.ToString(); | ||
277 | //docElement.Attributes.Append(attr); | ||
278 | |||
279 | |||
280 | XmlNode infoblock = basedoc.CreateNode(XmlNodeType.Element, "info", ""); | ||
281 | |||
282 | XmlNode infopiece = basedoc.CreateNode(XmlNodeType.Element, "uuid", ""); | ||
283 | infopiece.InnerText = scene.RegionInfo.RegionID.ToString(); | ||
284 | infoblock.AppendChild(infopiece); | ||
285 | |||
286 | infopiece = basedoc.CreateNode(XmlNodeType.Element, "url", ""); | ||
287 | infopiece.InnerText = "http://" + m_hostname + ":" + m_listener_port; | ||
288 | infoblock.AppendChild(infopiece); | ||
289 | |||
290 | infopiece = basedoc.CreateNode(XmlNodeType.Element, "name", ""); | ||
291 | infopiece.InnerText = scene.RegionInfo.RegionName; | ||
292 | infoblock.AppendChild(infopiece); | ||
293 | |||
294 | docElement.AppendChild(infoblock); | ||
295 | |||
296 | return docElement; | ||
297 | } | ||
298 | |||
299 | private XmlNode GetGridSnapshotData(XmlDocument factory) | ||
300 | { | ||
301 | XmlNode griddata = factory.CreateNode(XmlNodeType.Element, "grid", ""); | ||
302 | |||
303 | foreach (KeyValuePair<String, String> GridData in m_gridinfo) | ||
304 | { | ||
305 | //TODO: make it lowercase tag names for diva | ||
306 | XmlNode childnode = factory.CreateNode(XmlNodeType.Element, GridData.Key, ""); | ||
307 | childnode.InnerText = GridData.Value; | ||
308 | griddata.AppendChild(childnode); | ||
309 | } | ||
310 | |||
311 | return griddata; | ||
312 | } | ||
313 | |||
314 | private String GetRegionCategory(Scene scene) | ||
315 | { | ||
316 | |||
317 | //Boolean choice between: | ||
318 | // "PG" - Mormontown | ||
319 | // "Mature" - Sodom and Gomorrah | ||
320 | // (Depreciated) "Patriotic Nigra Testing Sandbox" - Abandon Hope All Ye Who Enter Here | ||
321 | if ((scene.RegionInfo.EstateSettings.simAccess & Simulator.SimAccess.Mature) == Simulator.SimAccess.Mature) | ||
322 | { | ||
323 | return "Mature"; | ||
324 | } | ||
325 | else if ((scene.RegionInfo.EstateSettings.simAccess & Simulator.SimAccess.PG) == Simulator.SimAccess.PG) | ||
326 | { | ||
327 | return "PG"; | ||
328 | } | ||
329 | else | ||
330 | { | ||
331 | return "Unknown"; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | /* Code's closed due to AIDS, See EstateSnapshot.cs for CURE | ||
336 | private XmlNode GetEstateSnapshotData(Scene scene, XmlDocument factory) | ||
337 | { | ||
338 | //Estate data section - contains who owns a set of sims and the name of the set. | ||
339 | //In Opensim all the estate names are the same as the Master Avatar (owner of the sim) | ||
340 | XmlNode estatedata = factory.CreateNode(XmlNodeType.Element, "estate", ""); | ||
341 | |||
342 | LLUUID ownerid = scene.RegionInfo.MasterAvatarAssignedUUID; | ||
343 | String firstname = scene.RegionInfo.MasterAvatarFirstName; | ||
344 | String lastname = scene.RegionInfo.MasterAvatarLastName; | ||
345 | String hostname = scene.RegionInfo.ExternalHostName; | ||
346 | |||
347 | XmlNode user = factory.CreateNode(XmlNodeType.Element, "owner", ""); | ||
348 | |||
349 | XmlNode username = factory.CreateNode(XmlNodeType.Element, "name", ""); | ||
350 | username.InnerText = firstname + " " + lastname; | ||
351 | user.AppendChild(username); | ||
352 | |||
353 | XmlNode useruuid = factory.CreateNode(XmlNodeType.Element, "uuid", ""); | ||
354 | useruuid.InnerText = ownerid.ToString(); | ||
355 | user.AppendChild(useruuid); | ||
356 | |||
357 | estatedata.AppendChild(user); | ||
358 | |||
359 | return estatedata; | ||
360 | } */ | ||
361 | |||
362 | #endregion | ||
363 | |||
364 | #region [Public] Snapshot storage functions | ||
365 | |||
366 | public void MakeNewSnapshot() | ||
367 | { | ||
368 | foreach (Scene scene in m_scenes) | ||
369 | { | ||
370 | XmlDocument snapshot = Snapshot(scene); | ||
371 | |||
372 | string path = DataFileName(scene); | ||
373 | |||
374 | try | ||
375 | { | ||
376 | using (XmlTextWriter snapXWriter = new XmlTextWriter(path, Encoding.Default)) | ||
377 | { | ||
378 | snapXWriter.Formatting = Formatting.Indented; | ||
379 | snapXWriter.WriteStartDocument(); | ||
380 | snapshot.WriteTo(snapXWriter); | ||
381 | snapXWriter.WriteEndDocument(); | ||
382 | |||
383 | m_lastSnapshot++; | ||
384 | } | ||
385 | } | ||
386 | catch (Exception e) | ||
387 | { | ||
388 | m_log.Warn("[DATASNAPSHOT]: Caught unknown exception while trying to save snapshot: " + path + "\n" + e.ToString()); | ||
389 | } | ||
390 | m_log.Info("[DATASNAPSHOT]: Made external data snapshot " + path); | ||
391 | } | ||
392 | } | ||
393 | |||
394 | /** | ||
395 | * Reply to the http request | ||
396 | */ | ||
397 | public XmlDocument GetSnapshot(string regionName) | ||
398 | { | ||
399 | XmlDocument requestedSnap = new XmlDocument(); | ||
400 | requestedSnap.AppendChild(requestedSnap.CreateXmlDeclaration("1.0", null, null)); | ||
401 | requestedSnap.AppendChild(requestedSnap.CreateWhitespace("\r\n")); | ||
402 | XmlNode regiondata = requestedSnap.CreateNode(XmlNodeType.Element, "regiondata", ""); | ||
403 | try | ||
404 | { | ||
405 | if (regionName == null || regionName == "") | ||
406 | { | ||
407 | foreach (Scene scene in m_scenes) | ||
408 | { | ||
409 | string path = DataFileName(scene); | ||
410 | XmlDocument regionSnap = new XmlDocument(); | ||
411 | regionSnap.PreserveWhitespace = true; | ||
412 | |||
413 | regionSnap.Load(path); | ||
414 | XmlNode nodeOrig = regionSnap["region"]; | ||
415 | XmlNode nodeDest = requestedSnap.ImportNode(nodeOrig, true); | ||
416 | //requestedSnap.AppendChild(nodeDest); | ||
417 | |||
418 | regiondata.AppendChild(requestedSnap.CreateWhitespace("\r\n")); | ||
419 | regiondata.AppendChild(nodeDest); | ||
420 | } | ||
421 | } | ||
422 | else | ||
423 | { | ||
424 | Scene scene = SceneForName(regionName); | ||
425 | requestedSnap.Load(DataFileName(scene)); | ||
426 | } | ||
427 | // requestedSnap.InsertBefore(requestedSnap.CreateXmlDeclaration("1.0", null, null), | ||
428 | // requestedSnap.DocumentElement); | ||
429 | requestedSnap.AppendChild(regiondata); | ||
430 | regiondata.AppendChild(requestedSnap.CreateWhitespace("\r\n")); | ||
431 | |||
432 | |||
433 | } | ||
434 | catch (XmlException e) | ||
435 | { | ||
436 | m_log.Warn("[DATASNAPSHOT]: XmlException while trying to load snapshot: " + e.ToString()); | ||
437 | requestedSnap = GetErrorMessage(regionName, e); | ||
438 | } | ||
439 | catch (Exception e) | ||
440 | { | ||
441 | m_log.Warn("[DATASNAPSHOT]: Caught unknown exception while trying to load snapshot: " + e.StackTrace); | ||
442 | requestedSnap = GetErrorMessage(regionName, e); | ||
443 | } | ||
444 | |||
445 | |||
446 | return requestedSnap; | ||
447 | } | ||
448 | |||
449 | private XmlDocument GetErrorMessage(string regionName, Exception e) | ||
450 | { | ||
451 | XmlDocument errorMessage = new XmlDocument(); | ||
452 | XmlNode error = errorMessage.CreateNode(XmlNodeType.Element, "error", ""); | ||
453 | XmlNode region = errorMessage.CreateNode(XmlNodeType.Element, "region", ""); | ||
454 | region.InnerText = regionName; | ||
455 | |||
456 | XmlNode exception = errorMessage.CreateNode(XmlNodeType.Element, "exception", ""); | ||
457 | exception.InnerText = e.ToString(); | ||
458 | |||
459 | error.AppendChild(region); | ||
460 | error.AppendChild(exception); | ||
461 | errorMessage.AppendChild(error); | ||
462 | |||
463 | return errorMessage; | ||
464 | } | ||
465 | |||
466 | #endregion | ||
467 | |||
468 | #region Event callbacks | ||
469 | |||
470 | private void SnapshotTimerCallback(object timer, ElapsedEventArgs args) | ||
471 | { | ||
472 | MakeNewSnapshot(); | ||
473 | //Add extra calls here | ||
474 | } | ||
475 | |||
476 | #endregion | ||
477 | |||
478 | #region External data services | ||
479 | private void NotifyDataServices(string servicesStr) | ||
480 | { | ||
481 | Stream reply = null; | ||
482 | string delimStr = ";"; | ||
483 | char [] delimiter = delimStr.ToCharArray(); | ||
484 | |||
485 | string[] services = servicesStr.Split(delimiter); | ||
486 | |||
487 | for (int i = 0; i < services.Length; i++) | ||
488 | { | ||
489 | string url = services[i].Trim(); | ||
490 | RestClient cli = new RestClient(url); | ||
491 | cli.AddQueryParameter("host", m_hostname); | ||
492 | cli.AddQueryParameter("port", m_listener_port); | ||
493 | cli.RequestMethod = "GET"; | ||
494 | try | ||
495 | { | ||
496 | reply = cli.Request(); | ||
497 | } | ||
498 | catch (System.Net.WebException) | ||
499 | { | ||
500 | m_log.Warn("[DATASNAPSHOT] Unable to notify " + url); | ||
501 | } | ||
502 | catch (Exception e) | ||
503 | { | ||
504 | m_log.Warn("[DATASNAPSHOT] Ignoring unknown exception " + e.ToString()); | ||
505 | } | ||
506 | byte[] response = new byte[1024]; | ||
507 | int n = 0; | ||
508 | try | ||
509 | { | ||
510 | n = reply.Read(response, 0, 1024); | ||
511 | } | ||
512 | catch (Exception e) | ||
513 | { | ||
514 | m_log.Warn("[DATASNAPSHOT] Unable to decode reply from data service. Ignoring. " + e.StackTrace); | ||
515 | } | ||
516 | // This is not quite working, so... | ||
517 | string responseStr = System.Text.ASCIIEncoding.UTF8.GetString(response); | ||
518 | m_log.Info("[DATASNAPSHOT] data service notified: " + url); | ||
519 | } | ||
520 | |||
521 | } | ||
522 | #endregion | ||
523 | } | ||
524 | } | ||