From df7fb207a87b1b07a00600d5b66e717ac2332b4f Mon Sep 17 00:00:00 2001
From: Mic Bowman
Date: Sat, 8 Jan 2011 13:33:07 -0800
Subject: Moved the map tile processing used by the Simian Grid Frontend into a
separate region module. Configuration settings added to the defaults ini
file. Others may find this useful for pushing map tiles to a separate server.
---
.../SimianGrid/SimianGridMaptileModule.cs | 261 +++++++++++++++++++++
.../SimianGrid/SimianGridServiceConnector.cs | 86 -------
2 files changed, 261 insertions(+), 86 deletions(-)
create mode 100644 OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs
(limited to 'OpenSim')
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs
new file mode 100644
index 0000000..dd8fe2b
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Net;
+using System.IO;
+using System.Timers;
+using System.Drawing;
+using System.Drawing.Imaging;
+
+using log4net;
+using Mono.Addins;
+using Nini.Config;
+using OpenSim.Framework;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.Framework.Scenes;
+using OpenMetaverse;
+using OpenMetaverse.StructuredData;
+
+namespace OpenSim.Region.OptionalModules.Simian
+{
+ ///
+ ///
+ ///
+ ///
+
+ [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianGridMaptile")]
+ public class SimianGridMaptile : ISharedRegionModule
+ {
+ private static readonly ILog m_log =
+ LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ private bool m_enabled = false;
+ private string m_serverUrl = String.Empty;
+ private Dictionary m_scenes = new Dictionary();
+
+ private int m_refreshtime = 0;
+ private int m_lastrefresh = 0;
+ private System.Timers.Timer m_refreshTimer = new System.Timers.Timer();
+
+ #region ISharedRegionModule
+
+ public Type ReplaceableInterface { get { return null; } }
+ public string Name { get { return "SimianGridMaptile"; } }
+ public void RegionLoaded(Scene scene) { }
+ public void Close() { }
+
+ ///
+ ///
+ ///
+ public void Initialise(IConfigSource source)
+ {
+ IConfig config = source.Configs["SimianGridMaptiles"];
+ if (config == null)
+ return;
+
+ if (! config.GetBoolean("Enabled", false))
+ return;
+
+ m_serverUrl = config.GetString("MaptileURL");
+ if (String.IsNullOrEmpty(m_serverUrl))
+ return;
+
+ m_refreshtime = Convert.ToInt32(config.GetString("RefreshTime"));
+ if (m_refreshtime <= 0)
+ return;
+
+ m_log.InfoFormat("[SIMIAN MAPTILE] enabled with refresh timeout {0} and URL {1}",
+ m_refreshtime,m_serverUrl);
+
+ m_enabled = true;
+ }
+
+ ///
+ ///
+ ///
+ public void PostInitialise()
+ {
+ if (m_enabled)
+ {
+ m_refreshTimer.Enabled = true;
+ m_refreshTimer.AutoReset = true;
+ m_refreshTimer.Interval = 5 * 60 * 1000; // every 5 minutes
+ m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh);
+ }
+ }
+
+
+ ///
+ ///
+ ///
+ public void AddRegion(Scene scene)
+ {
+ if (! m_enabled)
+ return;
+
+ // Every shared region module has to maintain an indepedent list of
+ // currently running regions
+ lock (m_scenes)
+ m_scenes[scene.RegionInfo.RegionID] = scene;
+ }
+
+ ///
+ ///
+ ///
+ public void RemoveRegion(Scene scene)
+ {
+ if (! m_enabled)
+ return;
+
+ lock (m_scenes)
+ m_scenes.Remove(scene.RegionInfo.RegionID);
+ }
+
+ #endregion ISharedRegionModule
+
+ ///
+ ///
+ ///
+ private void HandleMaptileRefresh(object sender, EventArgs ea)
+ {
+ // this approach is a bit convoluted becase we want to wait for the
+ // first upload to happen on startup but after all the objects are
+ // loaded and initialized
+ if (m_lastrefresh > 0 && Util.EnvironmentTickCountSubtract(m_lastrefresh) < m_refreshtime)
+ return;
+
+ m_log.DebugFormat("[SIMIAN MAPTILE] map refresh fired");
+ lock (m_scenes)
+ {
+ foreach (IScene scene in m_scenes.Values)
+ {
+ try
+ {
+ UploadMapTile(scene);
+ }
+ catch (Exception ex)
+ {
+ m_log.WarnFormat("[SIMIAN MAPTILE] something bad happened {0}",ex.Message);
+ }
+ }
+ }
+
+ m_lastrefresh = Util.EnvironmentTickCount();
+ }
+
+ ///
+ ///
+ ///
+ private void UploadMapTile(IScene scene)
+ {
+ m_log.DebugFormat("[SIMIAN MAPTILE]: upload maptile for {0}",scene.RegionInfo.RegionName);
+
+ // Create a PNG map tile and upload it to the AddMapTile API
+ byte[] pngData = Utils.EmptyBytes;
+ IMapImageGenerator tileGenerator = scene.RequestModuleInterface();
+ if (tileGenerator == null)
+ {
+ m_log.Warn("[SIMIAN MAPTILE]: Cannot upload PNG map tile without an ImageGenerator");
+ return;
+ }
+
+ using (Image mapTile = tileGenerator.CreateMapTile())
+ {
+ using (MemoryStream stream = new MemoryStream())
+ {
+ mapTile.Save(stream, ImageFormat.Png);
+ pngData = stream.ToArray();
+ }
+ }
+
+ List postParameters = new List()
+ {
+ new MultipartForm.Parameter("X", scene.RegionInfo.RegionLocX.ToString()),
+ new MultipartForm.Parameter("Y", scene.RegionInfo.RegionLocY.ToString()),
+ new MultipartForm.File("Tile", "tile.png", "image/png", pngData)
+ };
+
+ string errorMessage = null;
+ int tickstart = Util.EnvironmentTickCount();
+
+ // Make the remote storage request
+ try
+ {
+ HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl);
+ request.Timeout = 20000;
+ request.ReadWriteTimeout = 5000;
+
+ using (HttpWebResponse response = MultipartForm.Post(request, postParameters))
+ {
+ using (Stream responseStream = response.GetResponseStream())
+ {
+ string responseStr = responseStream.GetStreamString();
+ OSD responseOSD = OSDParser.Deserialize(responseStr);
+ if (responseOSD.Type == OSDType.Map)
+ {
+ OSDMap responseMap = (OSDMap)responseOSD;
+ if (responseMap["Success"].AsBoolean())
+ return;
+
+ errorMessage = "Upload failed: " + responseMap["Message"].AsString();
+ }
+ else
+ {
+ errorMessage = "Response format was invalid:\n" + responseStr;
+ }
+ }
+ }
+ }
+ catch (WebException we)
+ {
+ errorMessage = we.Message;
+ if (we.Status == WebExceptionStatus.ProtocolError)
+ {
+ HttpWebResponse webResponse = (HttpWebResponse)we.Response;
+ errorMessage = String.Format("[{0}] {1}",
+ webResponse.StatusCode,webResponse.StatusDescription);
+ }
+ }
+ catch (Exception ex)
+ {
+ errorMessage = ex.Message;
+ }
+ finally
+ {
+ // This just dumps a warning for any operation that takes more than 100 ms
+ int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
+ m_log.DebugFormat("[SIMIAN MAPTILE]: map tile uploaded in {0}ms",tickdiff);
+ }
+
+ m_log.WarnFormat("[SIMIAN MAPTILE]: Failed to store {0} byte tile for {1}: {2}",
+ pngData.Length, scene.RegionInfo.RegionName, errorMessage);
+ }
+ }
+}
\ No newline at end of file
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
index 9c72a61..18a31670 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
@@ -28,8 +28,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
-using System.Drawing;
-using System.Drawing.Imaging;
using System.IO;
using System.Net;
using System.Reflection;
@@ -102,13 +100,6 @@ namespace OpenSim.Services.Connectors.SimianGrid
public string RegisterRegion(UUID scopeID, GridRegion regionInfo)
{
- // Generate and upload our map tile in PNG format to the SimianGrid AddMapTile service
-// Scene scene;
-// if (m_scenes.TryGetValue(regionInfo.RegionID, out scene))
-// UploadMapTile(scene);
-// else
-// m_log.Warn("Registering region " + regionInfo.RegionName + " (" + regionInfo.RegionID + ") that we are not tracking");
-
Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0);
Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, 4096.0);
@@ -380,83 +371,6 @@ namespace OpenSim.Services.Connectors.SimianGrid
#endregion IGridService
- private void UploadMapTile(IScene scene)
- {
- string errorMessage = null;
-
- // Create a PNG map tile and upload it to the AddMapTile API
- byte[] pngData = Utils.EmptyBytes;
- IMapImageGenerator tileGenerator = scene.RequestModuleInterface();
- if (tileGenerator == null)
- {
- m_log.Warn("[SIMIAN GRID CONNECTOR]: Cannot upload PNG map tile without an IMapImageGenerator");
- return;
- }
-
- using (Image mapTile = tileGenerator.CreateMapTile())
- {
- using (MemoryStream stream = new MemoryStream())
- {
- mapTile.Save(stream, ImageFormat.Png);
- pngData = stream.ToArray();
- }
- }
-
- List postParameters = new List()
- {
- new MultipartForm.Parameter("X", scene.RegionInfo.RegionLocX.ToString()),
- new MultipartForm.Parameter("Y", scene.RegionInfo.RegionLocY.ToString()),
- new MultipartForm.File("Tile", "tile.png", "image/png", pngData)
- };
-
- // Make the remote storage request
- try
- {
- HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI);
-
- HttpWebResponse response = MultipartForm.Post(request, postParameters);
- using (Stream responseStream = response.GetResponseStream())
- {
- string responseStr = null;
-
- try
- {
- responseStr = responseStream.GetStreamString();
- OSD responseOSD = OSDParser.Deserialize(responseStr);
- if (responseOSD.Type == OSDType.Map)
- {
- OSDMap responseMap = (OSDMap)responseOSD;
- if (responseMap["Success"].AsBoolean())
- m_log.Info("[SIMIAN GRID CONNECTOR]: Uploaded " + pngData.Length + " byte PNG map tile to AddMapTile");
- else
- errorMessage = "Upload failed: " + responseMap["Message"].AsString();
- }
- else
- {
- errorMessage = "Response format was invalid:\n" + responseStr;
- }
- }
- catch (Exception ex)
- {
- if (!String.IsNullOrEmpty(responseStr))
- errorMessage = "Failed to parse the response:\n" + responseStr;
- else
- errorMessage = "Failed to retrieve the response: " + ex.Message;
- }
- }
- }
- catch (WebException ex)
- {
- errorMessage = ex.Message;
- }
-
- if (!String.IsNullOrEmpty(errorMessage))
- {
- m_log.WarnFormat("[SIMIAN GRID CONNECTOR]: Failed to store {0} byte PNG map tile for {1}: {2}",
- pngData.Length, scene.RegionInfo.RegionName, errorMessage.Replace('\n', ' '));
- }
- }
-
private GridRegion GetNearestRegion(Vector3d position, bool onlyEnabled)
{
NameValueCollection requestArgs = new NameValueCollection
--
cgit v1.1