* Implemented new InterRegion comms method in the form of InterregionModule

* Interfaces and methods have been defined for basic operation, however a replacement grid module is required to share region URIs with neighbours for this module to work.
* Tackling that next.
0.6.0-stable
Adam Frisby 2008-04-29 17:50:29 +00:00
parent 41207b5fa0
commit 03155e362c
4 changed files with 226 additions and 0 deletions

View File

@ -0,0 +1,14 @@
using OpenSim.Framework;
using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Modules.Communications.Interregion
{
public interface IInterregionModule
{
void RegisterMethod<T>(T e);
bool HasInterface<T>(Location loc);
T RequestInterface<T>(Location loc);
T[] RequestInterface<T>();
Location GetLocationByDirection(Scene scene, InterregionModule.Direction dir);
}
}

View File

@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using Nini.Config;
using OpenSim.Framework;
using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Modules.Communications.Interregion
{
public class InterregionModule : IInterregionModule, IRegionModule
{
#region Direction enum
public enum Direction
{
North,
NorthEast,
East,
SouthEast,
South,
SouthWest,
West,
NorthWest
}
#endregion
private readonly Dictionary<Type, Object> m_interfaces = new Dictionary<Type, object>();
private readonly List<Location> m_myLocations = new List<Location>();
private readonly Dictionary<Location, string[]> m_neighbourInterfaces = new Dictionary<Location, string[]>();
private readonly Dictionary<Location, RemotingObject> m_neighbourRemote = new Dictionary<Location, RemotingObject>();
private IConfigSource m_config;
private RemotingObject m_myRemote;
private TcpChannel m_tcpChannel;
private int m_tcpPort = 10101;
#region IRegionModule Members
public void Initialise(Scene scene, IConfigSource source)
{
m_myLocations.Add(new Location((int) scene.RegionInfo.RegionLocX,
(int) scene.RegionInfo.RegionLocY));
m_config = source;
scene.RegisterModuleInterface<IInterregionModule>(this);
}
//TODO: This prevents us from registering new scenes after PostInitialise if we want comms updated.
public void PostInitialise()
{
try
{
m_tcpPort = m_config.Configs["Comms"].GetInt("remoting_port", m_tcpPort);
}
catch
{
}
CreateRemotingObjects();
}
public void Close()
{
ChannelServices.UnregisterChannel(m_tcpChannel);
}
public string Name
{
get { return "InterregionModule"; }
}
public bool IsSharedModule
{
get { return true; }
}
#endregion
private void CreateRemotingObjects()
{
m_myRemote = new RemotingObject(m_interfaces, m_myLocations.ToArray());
m_tcpChannel = new TcpChannel(m_tcpPort);
ChannelServices.RegisterChannel(m_tcpChannel, false);
RemotingServices.Marshal(m_myRemote, "OpenSimRemote2", typeof (RemotingObject));
}
public void RegisterRemoteRegion(string uri)
{
RegisterRemotingInterface((RemotingObject) Activator.GetObject(typeof (RemotingObject), uri));
}
private void RegisterRemotingInterface(RemotingObject remote)
{
Location[] locs = remote.GetLocations();
string[] interfaces = remote.GetInterfaces();
foreach (Location loc in locs)
{
m_neighbourInterfaces[loc] = interfaces;
m_neighbourRemote[loc] = remote;
}
}
public void RegisterMethod<T>(T e)
{
m_interfaces[typeof (T)] = e;
}
public bool HasInterface<T>(Location loc)
{
foreach (string val in m_neighbourInterfaces[loc])
{
if (val == typeof (T).FullName)
{
return true;
}
}
return false;
}
public T RequestInterface<T>(Location loc)
{
if (m_neighbourRemote.ContainsKey(loc))
{
return m_neighbourRemote[loc].RequestInterface<T>();
}
else
{
throw new IndexOutOfRangeException("No neighbour availible at that location");
}
}
public T[] RequestInterface<T>()
{
List<T> m_t = new List<T>();
foreach (RemotingObject remote in m_neighbourRemote.Values)
{
try
{
m_t.Add(remote.RequestInterface<T>());
}
catch (NotSupportedException)
{
}
}
return m_t.ToArray();
}
public Location GetLocationByDirection(Scene scene, Direction dir)
{
return new Location(0, 0);
}
//TODO: This prevents us from registering new scenes after PostInitialise if we want comms updated.
}
}

View File

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using OpenSim.Framework;
namespace OpenSim.Region.Environment.Modules.Communications.Interregion
{
public class RemotingObject : MarshalByRefObject
{
private readonly Location[] m_coords;
private readonly Dictionary<Type, Object> m_interfaces = new Dictionary<Type, object>();
public RemotingObject(Dictionary<Type, Object> myInterfaces, Location[] coords)
{
m_interfaces = myInterfaces;
m_coords = coords;
}
public Location[] GetLocations()
{
return (Location[]) m_coords.Clone();
}
public string[] GetInterfaces()
{
string[] interfaces = new string[m_interfaces.Count];
int i = 0;
foreach (KeyValuePair<Type, object> pair in m_interfaces)
{
interfaces[i++] = pair.Key.FullName;
}
return interfaces;
}
/// <summary>
/// Returns a registered interface availible to neighbouring regions.
/// </summary>
/// <typeparam name="T">The type of interface you wish to request</typeparam>
/// <returns>A MarshalByRefObject inherited from this region inheriting the interface requested.</returns>
/// <remarks>All registered interfaces <b>MUST</b> inherit from MarshalByRefObject and use only serialisable types.</remarks>
public T RequestInterface<T>()
{
if (m_interfaces.ContainsKey(typeof (T)))
return (T) m_interfaces[typeof (T)];
throw new NotSupportedException("No such interface registered.");
}
}
}

View File

@ -783,6 +783,7 @@
<Reference name="System" localCopy="false"/>
<Reference name="System.Xml"/>
<Reference name="System.Drawing"/>
<Reference name="System.Runtime.Remoting"/>
<Reference name="libsecondlife.dll"/>
<Reference name="Axiom.MathLib.dll"/>
<Reference name="OpenSim.Framework"/>