From 34f4738159300ab6370e3db47df5187b6cea8771 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 22 Sep 2009 11:58:40 -0700 Subject: [PATCH] Added HGGridConnector and related code. --- .../Grid/HGGridConnector.cs | 304 ++++++++++++++++++ .../Grid/LocalGridServiceConnector.cs | 64 ++-- .../Grid/RemoteGridServiceConnector.cs | 34 +- .../Handlers/Grid/GridServerConnector.cs | 2 +- .../Grid/HypergridServiceConnector.cs | 155 +++++++++ prebuild.xml | 1 + 6 files changed, 521 insertions(+), 39 deletions(-) create mode 100644 OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/HGGridConnector.cs create mode 100644 OpenSim/Services/Connectors/Grid/HypergridServiceConnector.cs diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/HGGridConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/HGGridConnector.cs new file mode 100644 index 0000000000..b7e3213dac --- /dev/null +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/HGGridConnector.cs @@ -0,0 +1,304 @@ +/* + * 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 OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using OpenSim.Server.Base; +using OpenSim.Services.Connectors.Grid; + +using OpenMetaverse; +using log4net; +using Nini.Config; + +namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid +{ + public class HGGridConnector : ISharedRegionModule, IGridService + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private bool m_Enabled = false; + private bool m_Initialized = false; + + private IGridService m_GridServiceConnector; + private HypergridServiceConnector m_HypergridServiceConnector; + + // Hyperlink regions are hyperlinks on the map + protected Dictionary m_HyperlinkRegions = new Dictionary(); + + // Known regions are home regions of visiting foreign users. + // They are not on the map as static hyperlinks. They are dynamic hyperlinks, they go away when + // the visitor goes away. They are mapped to X=0 on the map. + // This is key-ed on agent ID + protected Dictionary m_knownRegions = new Dictionary(); + + #region ISharedRegionModule + + public Type ReplaceableInterface + { + get { return null; } + } + + public string Name + { + get { return "HGGridServicesConnector"; } + } + + public void Initialise(IConfigSource source) + { + IConfig moduleConfig = source.Configs["Modules"]; + if (moduleConfig != null) + { + string name = moduleConfig.GetString("GridServices", ""); + if (name == Name) + { + IConfig gridConfig = source.Configs["GridService"]; + if (gridConfig == null) + { + m_log.Error("[HGGRID CONNECTOR]: GridService missing from OpenSim.ini"); + return; + } + + + InitialiseConnectorModule(source); + + m_Enabled = true; + m_log.Info("[HGGRID CONNECTOR]: HG grid enabled"); + } + } + } + + private void InitialiseConnectorModule(IConfigSource source) + { + IConfig gridConfig = source.Configs["GridService"]; + if (gridConfig == null) + { + m_log.Error("[HGGRID CONNECTOR]: GridService missing from OpenSim.ini"); + throw new Exception("Grid connector init error"); + } + + string module = gridConfig.GetString("GridServiceConnectorModule", String.Empty); + if (module == String.Empty) + { + m_log.Error("[HGGRID CONNECTOR]: No GridServiceConnectorModule named in section GridService"); + //return; + throw new Exception("Unable to proceed. Please make sure your ini files in config-include are updated according to .example's"); + } + + Object[] args = new Object[] { source }; + m_GridServiceConnector = ServerUtils.LoadPlugin(module, args); + + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + scene.RegisterModuleInterface(this); + } + + public void RemoveRegion(Scene scene) + { + } + + public void RegionLoaded(Scene scene) + { + if (m_Enabled && !m_Initialized) + { + m_HypergridServiceConnector = new HypergridServiceConnector(scene.AssetService); + m_Initialized = true; + } + } + + #endregion + + #region IGridService + + public bool RegisterRegion(UUID scopeID, SimpleRegionInfo regionInfo) + { + // Region doesn't exist here. Trying to link remote region + if (regionInfo.RegionID.Equals(UUID.Zero)) + { + m_log.Info("[HGrid]: Linking remote region " + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort); + regionInfo.RegionID = m_HypergridServiceConnector.LinkRegion(regionInfo); + if (!regionInfo.RegionID.Equals(UUID.Zero)) + { + m_HyperlinkRegions.Add(regionInfo.RegionID, regionInfo); + m_log.Info("[HGrid]: Successfully linked to region_uuid " + regionInfo.RegionID); + + // Try get the map image + m_HypergridServiceConnector.GetMapImage(regionInfo); + return true; + } + else + { + m_log.Info("[HGrid]: No such region " + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort + "(" + regionInfo.InternalEndPoint.Port + ")"); + return false; + } + // Note that these remote regions aren't registered in localBackend, so return null, no local listeners + } + else // normal grid + return m_GridServiceConnector.RegisterRegion(scopeID, regionInfo); + } + + public bool DeregisterRegion(UUID regionID) + { + // Try the hyperlink collection + if (m_HyperlinkRegions.ContainsKey(regionID)) + { + m_HyperlinkRegions.Remove(regionID); + return true; + } + // Try the foreign users home collection + if (m_knownRegions.ContainsKey(regionID)) + { + m_knownRegions.Remove(regionID); + return true; + } + // Finally, try the normal route + return m_GridServiceConnector.DeregisterRegion(regionID); + } + + public List GetNeighbours(UUID scopeID, UUID regionID) + { + // No serving neighbours on hyperliked regions. + // Just the regular regions. + return m_GridServiceConnector.GetNeighbours(scopeID, regionID); + } + + public SimpleRegionInfo GetRegionByUUID(UUID scopeID, UUID regionID) + { + // Try the hyperlink collection + if (m_HyperlinkRegions.ContainsKey(regionID)) + return m_HyperlinkRegions[regionID]; + + // Try the foreign users home collection + if (m_knownRegions.ContainsKey(regionID)) + return m_knownRegions[regionID]; + + // Finally, try the normal route + return m_GridServiceConnector.GetRegionByUUID(scopeID, regionID); + } + + public SimpleRegionInfo GetRegionByPosition(UUID scopeID, int x, int y) + { + int snapX = (int) (x / Constants.RegionSize) * (int)Constants.RegionSize; + int snapY = (int) (y / Constants.RegionSize) * (int)Constants.RegionSize; + // Try the hyperlink collection + foreach (SimpleRegionInfo r in m_HyperlinkRegions.Values) + { + if ((r.RegionLocX == snapX) && (r.RegionLocY == snapY)) + return r; + } + + // Try the foreign users home collection + foreach (SimpleRegionInfo r in m_knownRegions.Values) + { + if ((r.RegionLocX == snapX) && (r.RegionLocY == snapY)) + return r; + } + + // Finally, try the normal route + return m_GridServiceConnector.GetRegionByPosition(scopeID, x, y); + } + + public SimpleRegionInfo GetRegionByName(UUID scopeID, string regionName) + { + // Try normal grid first + SimpleRegionInfo region = m_GridServiceConnector.GetRegionByName(scopeID, regionName); + if (region != null) + return region; + + // !!! Commenting until region name exists + //// Try the hyperlink collection + //foreach (SimpleRegionInfo r in m_HyperlinkRegions.Values) + //{ + // if (r.RegionName == regionName) + // return r; + //} + + //// Try the foreign users home collection + //foreach (SimpleRegionInfo r in m_knownRegions.Values) + //{ + // if (r.RegionName == regionName) + // return r; + //} + return null; + } + + public List GetRegionsByName(UUID scopeID, string name, int maxNumber) + { + List rinfos = new List(); + + // Commenting until regionname exists + //foreach (SimpleRegionInfo r in m_HyperlinkRegions.Values) + // if ((r.RegionName != null) && r.RegionName.StartsWith(name)) + // rinfos.Add(r); + + rinfos.AddRange(m_GridServiceConnector.GetRegionsByName(scopeID, name, maxNumber)); + return rinfos; + } + + public List GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax) + { + int snapXmin = (int)(xmin / Constants.RegionSize) * (int)Constants.RegionSize; + int snapXmax = (int)(xmax / Constants.RegionSize) * (int)Constants.RegionSize; + int snapYmin = (int)(ymin / Constants.RegionSize) * (int)Constants.RegionSize; + int snapYmax = (int)(ymax / Constants.RegionSize) * (int)Constants.RegionSize; + + List rinfos = new List(); + foreach (SimpleRegionInfo r in m_HyperlinkRegions.Values) + if ((r.RegionLocX > snapXmin) && (r.RegionLocX < snapYmax) && + (r.RegionLocY > snapYmin) && (r.RegionLocY < snapYmax)) + rinfos.Add(r); + + rinfos.AddRange(m_GridServiceConnector.GetRegionRange(scopeID, xmin, xmax, ymin, ymax)); + + return rinfos; + } + + #endregion + + + } +} diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs index 74ece2e6b0..3f294013d4 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs @@ -50,6 +50,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid private bool m_Enabled = false; + public LocalGridServicesConnector(IConfigSource source) + { + InitialiseService(source); + } + #region ISharedRegionModule public Type ReplaceableInterface @@ -70,38 +75,43 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid string name = moduleConfig.GetString("GridServices", ""); if (name == Name) { - IConfig assetConfig = source.Configs["GridService"]; - if (assetConfig == null) - { - m_log.Error("[GRID CONNECTOR]: GridService missing from OpenSim.ini"); - return; - } - - string serviceDll = assetConfig.GetString("LocalServiceModule", - String.Empty); - - if (serviceDll == String.Empty) - { - m_log.Error("[GRID CONNECTOR]: No LocalServiceModule named in section GridService"); - return; - } - - Object[] args = new Object[] { source }; - m_GridService = - ServerUtils.LoadPlugin(serviceDll, - args); - - if (m_GridService == null) - { - m_log.Error("[GRID CONNECTOR]: Can't load asset service"); - return; - } + InitialiseService(source); m_Enabled = true; - m_log.Info("[GRID CONNECTOR]: Local grid connector enabled"); + m_log.Info("[LOCAL GRID CONNECTOR]: Local grid connector enabled"); } } } + private void InitialiseService(IConfigSource source) + { + IConfig assetConfig = source.Configs["GridService"]; + if (assetConfig == null) + { + m_log.Error("[LOCAL GRID CONNECTOR]: GridService missing from OpenSim.ini"); + return; + } + + string serviceDll = assetConfig.GetString("LocalServiceModule", + String.Empty); + + if (serviceDll == String.Empty) + { + m_log.Error("[LOCAL GRID CONNECTOR]: No LocalServiceModule named in section GridService"); + return; + } + + Object[] args = new Object[] { source }; + m_GridService = + ServerUtils.LoadPlugin(serviceDll, + args); + + if (m_GridService == null) + { + m_log.Error("[LOCAL GRID CONNECTOR]: Can't load asset service"); + return; + } + } + public void PostInitialise() { } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs index b0cfc9cf0b..22b1015073 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs @@ -47,6 +47,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid private bool m_Enabled = false; + public RemoteGridServicesConnector(IConfigSource source) + { + InitialiseService(source); + } + + #region ISharedRegionmodule + public Type ReplaceableInterface { get { return null; } @@ -65,22 +72,25 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid string name = moduleConfig.GetString("GridServices", ""); if (name == Name) { - IConfig gridConfig = source.Configs["GridService"]; - if (gridConfig == null) - { - m_log.Error("[GRID CONNECTOR]: GridService missing from OpenSim.ini"); - return; - } - + InitialiseService(source); m_Enabled = true; - - base.Initialise(source); - - m_log.Info("[GRID CONNECTOR]: Remote grid enabled"); + m_log.Info("[REMOTE GRID CONNECTOR]: Remote grid enabled"); } } } + private void InitialiseService(IConfigSource source) + { + IConfig gridConfig = source.Configs["GridService"]; + if (gridConfig == null) + { + m_log.Error("[REMOTE GRID CONNECTOR]: GridService missing from OpenSim.ini"); + return; + } + + base.Initialise(source); + } + public void PostInitialise() { } @@ -104,5 +114,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid public void RegionLoaded(Scene scene) { } + + #endregion } } diff --git a/OpenSim/Server/Handlers/Grid/GridServerConnector.cs b/OpenSim/Server/Handlers/Grid/GridServerConnector.cs index b80c479072..7bf2e664d7 100644 --- a/OpenSim/Server/Handlers/Grid/GridServerConnector.cs +++ b/OpenSim/Server/Handlers/Grid/GridServerConnector.cs @@ -49,7 +49,7 @@ namespace OpenSim.Server.Handlers.Grid String.Empty); if (gridService == String.Empty) - throw new Exception("No AuthenticationService in config file"); + throw new Exception("No GridService in config file"); Object[] args = new Object[] { config }; m_GridService = ServerUtils.LoadPlugin(gridService, args); diff --git a/OpenSim/Services/Connectors/Grid/HypergridServiceConnector.cs b/OpenSim/Services/Connectors/Grid/HypergridServiceConnector.cs new file mode 100644 index 0000000000..f68c10a956 --- /dev/null +++ b/OpenSim/Services/Connectors/Grid/HypergridServiceConnector.cs @@ -0,0 +1,155 @@ +/* + * 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; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Net; +using System.Reflection; +using OpenSim.Services.Interfaces; + +using OpenSim.Framework; + +using OpenMetaverse; +using OpenMetaverse.Imaging; +using log4net; +using Nwc.XmlRpc; + +namespace OpenSim.Services.Connectors.Grid +{ + public class HypergridServiceConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IAssetService m_AssetService; + + public HypergridServiceConnector(IAssetService assService) + { + m_AssetService = assService; + } + + public UUID LinkRegion(SimpleRegionInfo info) + { + UUID uuid = UUID.Zero; + + //Hashtable hash = new Hashtable(); + //hash["region_name"] = info.RegionName; + + //IList paramList = new ArrayList(); + //paramList.Add(hash); + + //XmlRpcRequest request = new XmlRpcRequest("link_region", paramList); + //string uri = "http://" + info.ExternalEndPoint.Address + ":" + info.HttpPort + "/"; + //m_log.Debug("[HGrid]: Linking to " + uri); + //XmlRpcResponse response = request.Send(uri, 10000); + //if (response.IsFault) + //{ + // m_log.ErrorFormat("[HGrid]: remote call returned an error: {0}", response.FaultString); + //} + //else + //{ + // hash = (Hashtable)response.Value; + // //foreach (Object o in hash) + // // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + // try + // { + // UUID.TryParse((string)hash["uuid"], out uuid); + // info.RegionID = uuid; + // if ((string)hash["handle"] != null) + // { + // info.regionSecret = (string)hash["handle"]; + // //m_log.Debug(">> HERE: " + info.regionSecret); + // } + // if (hash["region_image"] != null) + // { + // UUID img = UUID.Zero; + // UUID.TryParse((string)hash["region_image"], out img); + // info.RegionSettings.TerrainImageID = img; + // } + // if (hash["region_name"] != null) + // { + // info.RegionName = (string)hash["region_name"]; + // //m_log.Debug(">> " + info.RegionName); + // } + // if (hash["internal_port"] != null) + // { + // int port = Convert.ToInt32((string)hash["internal_port"]); + // info.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), port); + // //m_log.Debug(">> " + info.InternalEndPoint.ToString()); + // } + // if (hash["remoting_port"] != null) + // { + // info.RemotingPort = Convert.ToUInt32(hash["remoting_port"]); + // //m_log.Debug(">> " + info.RemotingPort); + // } + + // } + // catch (Exception e) + // { + // m_log.Error("[HGrid]: Got exception while parsing hyperlink response " + e.StackTrace); + // } + //} + return uuid; + } + + public void GetMapImage(SimpleRegionInfo info) + { + try + { + string regionimage = "regionImage" + info.RegionID.ToString(); + regionimage = regionimage.Replace("-", ""); + + WebClient c = new WebClient(); + string uri = "http://" + info.ExternalHostName + ":" + info.HttpPort + "/index.php?method=" + regionimage; + //m_log.Debug("JPEG: " + uri); + c.DownloadFile(uri, info.RegionID.ToString() + ".jpg"); + Bitmap m = new Bitmap(info.RegionID.ToString() + ".jpg"); + //m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width); + byte[] imageData = OpenJPEG.EncodeFromImage(m, true); + AssetBase ass = new AssetBase(UUID.Random(), "region " + info.RegionID.ToString()); + + // !!! for now + //info.RegionSettings.TerrainImageID = ass.FullID; + + ass.Type = (int)AssetType.Texture; + ass.Temporary = true; + ass.Local = true; + ass.Data = imageData; + + m_AssetService.Store(ass); + + } + catch // LEGIT: Catching problems caused by OpenJPEG p/invoke + { + m_log.Warn("[HGrid]: Failed getting/storing map image, because it is probably already in the cache"); + } + } + + } +} diff --git a/prebuild.xml b/prebuild.xml index 2265b099e3..b131019aad 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1205,6 +1205,7 @@ ../../../bin/ +