Merge branch 'master' into httptests
commit
cb23d1bf24
|
@ -51,7 +51,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
private static string LogHeader = "[LOCAL GRID SERVICE CONNECTOR]";
|
private static string LogHeader = "[LOCAL GRID SERVICE CONNECTOR]";
|
||||||
|
|
||||||
private IGridService m_GridService;
|
private IGridService m_GridService;
|
||||||
private Dictionary<UUID, RegionCache> m_LocalCache = new Dictionary<UUID, RegionCache>();
|
private RegionInfoCache m_RegionInfoCache = null;
|
||||||
|
|
||||||
private bool m_Enabled;
|
private bool m_Enabled;
|
||||||
|
|
||||||
|
@ -60,10 +60,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
m_log.DebugFormat("{0} LocalGridServicesConnector no parms.", LogHeader);
|
m_log.DebugFormat("{0} LocalGridServicesConnector no parms.", LogHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalGridServicesConnector(IConfigSource source)
|
public LocalGridServicesConnector(IConfigSource source, RegionInfoCache regionInfoCache)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("{0} LocalGridServicesConnector instantiated directly.", LogHeader);
|
m_log.DebugFormat("{0} LocalGridServicesConnector instantiated directly.", LogHeader);
|
||||||
InitialiseService(source);
|
InitialiseService(source, regionInfoCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region ISharedRegionModule
|
#region ISharedRegionModule
|
||||||
|
@ -86,19 +86,25 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
string name = moduleConfig.GetString("GridServices", "");
|
string name = moduleConfig.GetString("GridServices", "");
|
||||||
if (name == Name)
|
if (name == Name)
|
||||||
{
|
{
|
||||||
InitialiseService(source);
|
|
||||||
|
if(InitialiseService(source,null))
|
||||||
m_log.Info("[LOCAL GRID SERVICE CONNECTOR]: Local grid connector enabled");
|
m_log.Info("[LOCAL GRID SERVICE CONNECTOR]: Local grid connector enabled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitialiseService(IConfigSource source)
|
private bool InitialiseService(IConfigSource source, RegionInfoCache ric)
|
||||||
{
|
{
|
||||||
|
if(ric == null)
|
||||||
|
m_RegionInfoCache = new RegionInfoCache();
|
||||||
|
else
|
||||||
|
m_RegionInfoCache = ric;
|
||||||
|
|
||||||
IConfig config = source.Configs["GridService"];
|
IConfig config = source.Configs["GridService"];
|
||||||
if (config == null)
|
if (config == null)
|
||||||
{
|
{
|
||||||
m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: GridService missing from OpenSim.ini");
|
m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: GridService missing from OpenSim.ini");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
string serviceDll = config.GetString("LocalServiceModule", String.Empty);
|
string serviceDll = config.GetString("LocalServiceModule", String.Empty);
|
||||||
|
@ -106,7 +112,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
if (serviceDll == String.Empty)
|
if (serviceDll == String.Empty)
|
||||||
{
|
{
|
||||||
m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: No LocalServiceModule named in section GridService");
|
m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: No LocalServiceModule named in section GridService");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object[] args = new Object[] { source };
|
Object[] args = new Object[] { source };
|
||||||
|
@ -117,10 +123,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
if (m_GridService == null)
|
if (m_GridService == null)
|
||||||
{
|
{
|
||||||
m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: Can't load grid service");
|
m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: Can't load grid service");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Enabled = true;
|
m_Enabled = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PostInitialise()
|
public void PostInitialise()
|
||||||
|
@ -143,13 +150,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
|
|
||||||
scene.RegisterModuleInterface<IGridService>(this);
|
scene.RegisterModuleInterface<IGridService>(this);
|
||||||
|
|
||||||
lock (m_LocalCache)
|
m_RegionInfoCache.CacheLocal(new GridRegion(scene.RegionInfo));
|
||||||
{
|
scene.EventManager.OnRegionUp += OnRegionUp;
|
||||||
if (m_LocalCache.ContainsKey(scene.RegionInfo.RegionID))
|
|
||||||
m_log.ErrorFormat("[LOCAL GRID SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!");
|
|
||||||
else
|
|
||||||
m_LocalCache.Add(scene.RegionInfo.RegionID, new RegionCache(scene));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveRegion(Scene scene)
|
public void RemoveRegion(Scene scene)
|
||||||
|
@ -157,11 +159,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
if (!m_Enabled)
|
if (!m_Enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock (m_LocalCache)
|
m_RegionInfoCache.Remove(scene.RegionInfo.ScopeID, scene.RegionInfo.RegionID);
|
||||||
{
|
scene.EventManager.OnRegionUp -= OnRegionUp;
|
||||||
m_LocalCache[scene.RegionInfo.RegionID].Clear();
|
|
||||||
m_LocalCache.Remove(scene.RegionInfo.RegionID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegionLoaded(Scene scene)
|
public void RegionLoaded(Scene scene)
|
||||||
|
@ -172,6 +171,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
|
|
||||||
#region IGridService
|
#region IGridService
|
||||||
|
|
||||||
|
private void OnRegionUp(GridRegion region)
|
||||||
|
{
|
||||||
|
// This shouldn't happen
|
||||||
|
if (region == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_RegionInfoCache.CacheNearNeighbour(region.ScopeID, region);
|
||||||
|
}
|
||||||
|
|
||||||
public string RegisterRegion(UUID scopeID, GridRegion regionInfo)
|
public string RegisterRegion(UUID scopeID, GridRegion regionInfo)
|
||||||
{
|
{
|
||||||
return m_GridService.RegisterRegion(scopeID, regionInfo);
|
return m_GridService.RegisterRegion(scopeID, regionInfo);
|
||||||
|
@ -189,7 +197,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
|
|
||||||
public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
|
public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
|
||||||
{
|
{
|
||||||
return m_GridService.GetRegionByUUID(scopeID, regionID);
|
bool inCache = false;
|
||||||
|
GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionID,out inCache);
|
||||||
|
if (inCache)
|
||||||
|
return rinfo;
|
||||||
|
|
||||||
|
rinfo = m_GridService.GetRegionByUUID(scopeID, regionID);
|
||||||
|
if(rinfo != null)
|
||||||
|
m_RegionInfoCache.Cache(scopeID, rinfo);
|
||||||
|
return rinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a region given its base coordinates.
|
// Get a region given its base coordinates.
|
||||||
|
@ -197,52 +213,37 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
// be the base coordinate of the region.
|
// be the base coordinate of the region.
|
||||||
public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
|
public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
|
||||||
{
|
{
|
||||||
GridRegion region = null;
|
// try in cache by handler first
|
||||||
uint regionX = Util.WorldToRegionLoc((uint)x);
|
ulong regionHandle = Util.RegionWorldLocToHandle((uint)x, (uint)y);
|
||||||
uint regionY = Util.WorldToRegionLoc((uint)y);
|
|
||||||
|
|
||||||
// First see if it's a neighbour, even if it isn't on this sim.
|
bool inCache = false;
|
||||||
// Neighbour data is cached in memory, so this is fast
|
GridRegion rinfo = m_RegionInfoCache.Get(scopeID, regionHandle, out inCache);
|
||||||
|
if (inCache)
|
||||||
|
return rinfo;
|
||||||
|
|
||||||
lock (m_LocalCache)
|
// try in cache by slower position next
|
||||||
{
|
rinfo = m_RegionInfoCache.Get(scopeID, x, y, out inCache);
|
||||||
foreach (RegionCache rcache in m_LocalCache.Values)
|
if (inCache)
|
||||||
{
|
return rinfo;
|
||||||
region = rcache.GetRegionByPosition(x, y);
|
|
||||||
if (region != null)
|
|
||||||
{
|
|
||||||
//m_log.DebugFormat("{0} GetRegionByPosition. Found region {1} in cache (of region {2}). Pos=<{3},{4}>",
|
|
||||||
// LogHeader, region.RegionName, rcache.RegionName,
|
|
||||||
// Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then try on this sim (may be a lookup in DB if this is using MySql).
|
// Then try on this sim (may be a lookup in DB if this is using MySql).
|
||||||
if (region == null)
|
rinfo = m_GridService.GetRegionByPosition(scopeID, x, y);
|
||||||
{
|
if(rinfo != null)
|
||||||
region = m_GridService.GetRegionByPosition(scopeID, x, y);
|
m_RegionInfoCache.Cache(scopeID, rinfo);
|
||||||
|
return rinfo;
|
||||||
if (region == null)
|
|
||||||
{
|
|
||||||
m_log.DebugFormat("{0} GetRegionByPosition. Region not found by grid service. Pos=<{1},{2}>",
|
|
||||||
LogHeader, regionX, regionY);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_log.DebugFormat("{0} GetRegionByPosition. Got region {1} from grid service. Pos=<{2},{3}>",
|
|
||||||
LogHeader, region.RegionName,
|
|
||||||
Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return region;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GridRegion GetRegionByName(UUID scopeID, string regionName)
|
public GridRegion GetRegionByName(UUID scopeID, string regionName)
|
||||||
{
|
{
|
||||||
return m_GridService.GetRegionByName(scopeID, regionName);
|
bool inCache = false;
|
||||||
|
GridRegion rinfo = m_RegionInfoCache.Get(scopeID, regionName, out inCache);
|
||||||
|
if (inCache)
|
||||||
|
return rinfo;
|
||||||
|
|
||||||
|
rinfo = m_GridService.GetRegionByName(scopeID, regionName);
|
||||||
|
if(rinfo != null)
|
||||||
|
m_RegionInfoCache.Cache(scopeID, rinfo);
|
||||||
|
return rinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber)
|
public List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber)
|
||||||
|
@ -290,7 +291,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
public void HandleShowNeighboursCommand(string module, string[] cmdparams)
|
public void HandleShowNeighboursCommand(string module, string[] cmdparams)
|
||||||
{
|
{
|
||||||
System.Text.StringBuilder caps = new System.Text.StringBuilder();
|
System.Text.StringBuilder caps = new System.Text.StringBuilder();
|
||||||
|
/* temporary broken
|
||||||
lock (m_LocalCache)
|
lock (m_LocalCache)
|
||||||
{
|
{
|
||||||
foreach (KeyValuePair<UUID, RegionCache> kvp in m_LocalCache)
|
foreach (KeyValuePair<UUID, RegionCache> kvp in m_LocalCache)
|
||||||
|
@ -303,6 +304,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
}
|
}
|
||||||
|
|
||||||
MainConsole.Instance.Output(caps.ToString());
|
MainConsole.Instance.Output(caps.ToString());
|
||||||
|
*/
|
||||||
|
MainConsole.Instance.Output("Neighbours list not avaiable in this version\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,103 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.Scenes;
|
|
||||||
using OpenSim.Services.Interfaces;
|
|
||||||
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
|
||||||
|
|
||||||
using OpenMetaverse;
|
|
||||||
using log4net;
|
|
||||||
|
|
||||||
namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
|
||||||
{
|
|
||||||
public class RegionCache
|
|
||||||
{
|
|
||||||
private static readonly ILog m_log =
|
|
||||||
LogManager.GetLogger(
|
|
||||||
MethodBase.GetCurrentMethod().DeclaringType);
|
|
||||||
|
|
||||||
private Scene m_scene;
|
|
||||||
private Dictionary<ulong, GridRegion> m_neighbours = new Dictionary<ulong, GridRegion>();
|
|
||||||
|
|
||||||
public string RegionName
|
|
||||||
{
|
|
||||||
get { return m_scene.RegionInfo.RegionName; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public RegionCache(Scene s)
|
|
||||||
{
|
|
||||||
m_scene = s;
|
|
||||||
m_scene.EventManager.OnRegionUp += OnRegionUp;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnRegionUp(GridRegion otherRegion)
|
|
||||||
{
|
|
||||||
// This shouldn't happen
|
|
||||||
if (otherRegion == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_log.DebugFormat("[REGION CACHE]: (on region {0}) Region {1} is up @ {2}-{3}",
|
|
||||||
m_scene.RegionInfo.RegionName, otherRegion.RegionName, Util.WorldToRegionLoc((uint)otherRegion.RegionLocX), Util.WorldToRegionLoc((uint)otherRegion.RegionLocY));
|
|
||||||
|
|
||||||
m_neighbours[otherRegion.RegionHandle] = otherRegion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
m_scene.EventManager.OnRegionUp -= OnRegionUp;
|
|
||||||
m_neighbours.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<GridRegion> GetNeighbours()
|
|
||||||
{
|
|
||||||
return new List<GridRegion>(m_neighbours.Values);
|
|
||||||
}
|
|
||||||
|
|
||||||
public GridRegion GetRegionByPosition(int x, int y)
|
|
||||||
{
|
|
||||||
// do actual search by position
|
|
||||||
// not the best, but this will not hold that many regions
|
|
||||||
GridRegion foundRegion = null;
|
|
||||||
foreach(GridRegion r in m_neighbours.Values)
|
|
||||||
{
|
|
||||||
if (x >= r.RegionLocX && x < r.RegionLocX + r.RegionSizeX
|
|
||||||
&& y >= r.RegionLocY && y < r.RegionLocY + r.RegionSizeY)
|
|
||||||
{
|
|
||||||
foundRegion = r;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return foundRegion;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -59,26 +59,42 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
|
|
||||||
public void Cache(UUID scopeID, GridRegion rinfo)
|
public void Cache(UUID scopeID, GridRegion rinfo)
|
||||||
{
|
{
|
||||||
// for now, do not cache negative results; this is because
|
|
||||||
// we need to figure out how to handle regions coming online
|
|
||||||
// in a timely way
|
|
||||||
if (rinfo == null)
|
if (rinfo == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS);
|
m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CacheLocal(GridRegion rinfo)
|
||||||
|
{
|
||||||
|
if (rinfo == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_Cache.AddOrUpdate(rinfo.ScopeID, rinfo, 1e7f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CacheNearNeighbour(UUID scopeID, GridRegion rinfo)
|
||||||
|
{
|
||||||
|
if (rinfo == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS);
|
||||||
|
m_Cache.Add(scopeID, rinfo, CACHE_EXPIRATION_SECONDS); // don't override local regions
|
||||||
|
}
|
||||||
|
|
||||||
public void Cache(UUID scopeID, GridRegion rinfo, float expireSeconds)
|
public void Cache(UUID scopeID, GridRegion rinfo, float expireSeconds)
|
||||||
{
|
{
|
||||||
// for now, do not cache negative results; this is because
|
|
||||||
// we need to figure out how to handle regions coming online
|
|
||||||
// in a timely way
|
|
||||||
if (rinfo == null)
|
if (rinfo == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_Cache.AddOrUpdate(scopeID, rinfo, expireSeconds);
|
m_Cache.AddOrUpdate(scopeID, rinfo, expireSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Remove(UUID scopeID, UUID regionID)
|
||||||
|
{
|
||||||
|
m_Cache.Remove(scopeID, regionID);
|
||||||
|
}
|
||||||
|
|
||||||
public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache)
|
public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache)
|
||||||
{
|
{
|
||||||
inCache = false;
|
inCache = false;
|
||||||
|
@ -134,43 +150,47 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// following code partialy adapted from lib OpenMetaverse
|
// following code partialy adapted from lib OpenMetaverse
|
||||||
public class RegionKey : IComparable<RegionKey>
|
public class RegionKey
|
||||||
{
|
{
|
||||||
private UUID m_scopeID;
|
public UUID ScopeID;
|
||||||
private UUID m_RegionID;
|
public UUID RegionID;
|
||||||
private DateTime m_expirationDate;
|
|
||||||
|
|
||||||
public RegionKey(UUID scopeID, UUID id)
|
public RegionKey(UUID scopeID, UUID id)
|
||||||
{
|
{
|
||||||
m_scopeID = scopeID;
|
ScopeID = scopeID;
|
||||||
m_RegionID = id;
|
RegionID = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID ScopeID
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
get { return m_scopeID; }
|
int hash = ScopeID.GetHashCode();
|
||||||
}
|
hash += hash * 23 + RegionID.GetHashCode();
|
||||||
public DateTime ExpirationDate
|
|
||||||
{
|
|
||||||
get { return m_expirationDate; }
|
|
||||||
set { m_expirationDate = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetHaskCode()
|
|
||||||
{
|
|
||||||
int hash = m_scopeID.GetHashCode();
|
|
||||||
hash += hash * 23 + m_RegionID.GetHashCode();
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CompareTo(RegionKey other)
|
public override bool Equals(Object b)
|
||||||
{
|
{
|
||||||
return GetHashCode().CompareTo(other.GetHashCode());
|
if(b == null)
|
||||||
|
return false;
|
||||||
|
RegionKey kb = b as RegionKey;
|
||||||
|
return (ScopeID == kb.ScopeID && RegionID == kb.RegionID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RegionKeyEqual : EqualityComparer<RegionKey>
|
||||||
|
{
|
||||||
|
public override int GetHashCode(RegionKey rk)
|
||||||
|
{
|
||||||
|
return rk.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(RegionKey a, RegionKey b)
|
||||||
|
{
|
||||||
|
return (a.ScopeID == b.ScopeID && a.RegionID == b.RegionID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +266,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class RegionsExpiringCache
|
public class RegionsExpiringCache
|
||||||
{
|
{
|
||||||
const double CACHE_PURGE_HZ = 60; // seconds
|
const double CACHE_PURGE_HZ = 60; // seconds
|
||||||
const int MAX_LOCK_WAIT = 10000; // milliseconds
|
const int MAX_LOCK_WAIT = 10000; // milliseconds
|
||||||
|
@ -256,7 +276,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
/// <summary>For thread safety</summary>
|
/// <summary>For thread safety</summary>
|
||||||
object isPurging = new object();
|
object isPurging = new object();
|
||||||
|
|
||||||
Dictionary<RegionKey, GridRegion> timedStorage = new Dictionary<RegionKey, GridRegion>();
|
static RegionKeyEqual keyequal = new RegionKeyEqual();
|
||||||
|
Dictionary<RegionKey, GridRegion> timedStorage = new Dictionary<RegionKey, GridRegion>(keyequal);
|
||||||
|
Dictionary<RegionKey, DateTime> timedExpires = new Dictionary<RegionKey, DateTime>();
|
||||||
Dictionary<UUID, RegionInfoByScope> InfobyScope = new Dictionary<UUID, RegionInfoByScope>();
|
Dictionary<UUID, RegionInfoByScope> InfobyScope = new Dictionary<UUID, RegionInfoByScope>();
|
||||||
private System.Timers.Timer timer = new System.Timers.Timer(TimeSpan.FromSeconds(CACHE_PURGE_HZ).TotalMilliseconds);
|
private System.Timers.Timer timer = new System.Timers.Timer(TimeSpan.FromSeconds(CACHE_PURGE_HZ).TotalMilliseconds);
|
||||||
|
|
||||||
|
@ -278,8 +300,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
if (timedStorage.ContainsKey(key))
|
if (timedStorage.ContainsKey(key))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
key.ExpirationDate = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
|
DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
|
||||||
timedStorage.Add(key, region);
|
timedStorage[key] = region;
|
||||||
|
timedExpires[key] = expire;
|
||||||
|
|
||||||
RegionInfoByScope ris = null;
|
RegionInfoByScope ris = null;
|
||||||
if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
|
if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
|
||||||
|
@ -303,12 +326,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RegionKey key = new RegionKey(scope, region.RegionID);
|
RegionKey key = new RegionKey(scope, region.RegionID);
|
||||||
key.ExpirationDate = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
|
DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
|
||||||
|
|
||||||
if (timedStorage.ContainsKey(key))
|
if (timedStorage.ContainsKey(key))
|
||||||
{
|
{
|
||||||
timedStorage.Remove(key);
|
timedStorage[key] = region;
|
||||||
timedStorage.Add(key, region);
|
if(expire > timedExpires[key])
|
||||||
|
timedExpires[key] = expire;
|
||||||
|
|
||||||
if(!InfobyScope.ContainsKey(scope))
|
if(!InfobyScope.ContainsKey(scope))
|
||||||
{
|
{
|
||||||
|
@ -319,7 +343,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
timedStorage.Add(key, region);
|
timedStorage[key] = region;
|
||||||
|
timedExpires[key] = expire;
|
||||||
RegionInfoByScope ris = null;
|
RegionInfoByScope ris = null;
|
||||||
if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
|
if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
|
||||||
{
|
{
|
||||||
|
@ -341,6 +366,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
timedStorage.Clear();
|
timedStorage.Clear();
|
||||||
|
timedExpires.Clear();
|
||||||
InfobyScope.Clear();
|
InfobyScope.Clear();
|
||||||
}
|
}
|
||||||
finally { Monitor.Exit(syncRoot); }
|
finally { Monitor.Exit(syncRoot); }
|
||||||
|
@ -370,10 +396,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
return timedStorage.Count;
|
return timedStorage.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Remove(UUID scope, GridRegion region)
|
public bool Remove(UUID scope, GridRegion region)
|
||||||
{
|
{
|
||||||
RegionKey key = new RegionKey(scope, region.RegionID);
|
return Remove(scope, region.RegionID);
|
||||||
|
}
|
||||||
|
public bool Remove(UUID scope, UUID regionID)
|
||||||
|
{
|
||||||
|
RegionKey key = new RegionKey(scope, regionID);
|
||||||
|
|
||||||
if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
|
if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
|
||||||
throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
|
throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
|
||||||
|
@ -391,6 +420,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
InfobyScope.Remove(scope);
|
InfobyScope.Remove(scope);
|
||||||
}
|
}
|
||||||
timedStorage.Remove(key);
|
timedStorage.Remove(key);
|
||||||
|
timedExpires.Remove(key);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -544,9 +574,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
if (!timedStorage.ContainsKey(key))
|
if (!timedStorage.ContainsKey(key))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
timedStorage.Remove(key);
|
DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
|
||||||
key.ExpirationDate = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
|
timedStorage[key] = region;
|
||||||
timedStorage.Add(key, region);
|
if(expire > timedExpires[key])
|
||||||
|
timedExpires[key] = expire;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
finally { Monitor.Exit(syncRoot); }
|
finally { Monitor.Exit(syncRoot); }
|
||||||
|
@ -572,26 +604,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
return;
|
return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
OpenMetaverse.Lazy<List<object>> expiredItems = new OpenMetaverse.Lazy<List<object>>();
|
List<RegionKey> expiredkeys = new List<RegionKey>();
|
||||||
|
|
||||||
foreach (RegionKey timedKey in timedStorage.Keys)
|
foreach (KeyValuePair<RegionKey, DateTime> kvp in timedExpires)
|
||||||
{
|
{
|
||||||
if (timedKey.ExpirationDate < signalTime)
|
if (kvp.Value < signalTime)
|
||||||
{
|
expiredkeys.Add(kvp.Key);
|
||||||
// Mark the object for purge
|
|
||||||
expiredItems.Value.Add(timedKey);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (expiredkeys.Count > 0)
|
||||||
|
{
|
||||||
RegionInfoByScope ris;
|
RegionInfoByScope ris;
|
||||||
if (expiredItems.IsValueCreated)
|
foreach (RegionKey key in expiredkeys)
|
||||||
{
|
|
||||||
foreach (RegionKey key in expiredItems.Value)
|
|
||||||
{
|
{
|
||||||
ris = null;
|
ris = null;
|
||||||
if(InfobyScope.TryGetValue(key.ScopeID, out ris) && ris != null)
|
if(InfobyScope.TryGetValue(key.ScopeID, out ris) && ris != null)
|
||||||
|
@ -604,6 +628,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
InfobyScope.Remove(key.ScopeID);
|
InfobyScope.Remove(key.ScopeID);
|
||||||
}
|
}
|
||||||
timedStorage.Remove(key);
|
timedStorage.Remove(key);
|
||||||
|
timedExpires.Remove(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,38 +87,46 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
string name = moduleConfig.GetString("GridServices", "");
|
string name = moduleConfig.GetString("GridServices", "");
|
||||||
if (name == Name)
|
if (name == Name)
|
||||||
{
|
{
|
||||||
InitialiseServices(source);
|
if(InitialiseServices(source))
|
||||||
|
{
|
||||||
m_Enabled = true;
|
m_Enabled = true;
|
||||||
m_log.Info("[REMOTE GRID CONNECTOR]: Remote grid enabled");
|
m_log.Info("[REMOTE GRID CONNECTOR]: Remote grid enabled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void InitialiseServices(IConfigSource source)
|
private bool InitialiseServices(IConfigSource source)
|
||||||
{
|
{
|
||||||
IConfig gridConfig = source.Configs["GridService"];
|
IConfig gridConfig = source.Configs["GridService"];
|
||||||
if (gridConfig == null)
|
if (gridConfig == null)
|
||||||
{
|
{
|
||||||
m_log.Error("[REMOTE GRID CONNECTOR]: GridService missing from OpenSim.ini");
|
m_log.Error("[REMOTE GRID CONNECTOR]: GridService missing from OpenSim.ini");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
string networkConnector = gridConfig.GetString("NetworkConnector", string.Empty);
|
string networkConnector = gridConfig.GetString("NetworkConnector", string.Empty);
|
||||||
if (networkConnector == string.Empty)
|
if (networkConnector == string.Empty)
|
||||||
{
|
{
|
||||||
m_log.Error("[REMOTE GRID CONNECTOR]: Please specify a network connector under [GridService]");
|
m_log.Error("[REMOTE GRID CONNECTOR]: Please specify a network connector under [GridService]");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object[] args = new Object[] { source };
|
Object[] args = new Object[] { source };
|
||||||
m_RemoteGridService = ServerUtils.LoadPlugin<IGridService>(networkConnector, args);
|
m_RemoteGridService = ServerUtils.LoadPlugin<IGridService>(networkConnector, args);
|
||||||
|
|
||||||
m_LocalGridService = new LocalGridServicesConnector(source);
|
m_LocalGridService = new LocalGridServicesConnector(source, m_RegionInfoCache);
|
||||||
|
if (m_LocalGridService == null)
|
||||||
|
{
|
||||||
|
m_log.Error("[REMOTE GRID CONNECTOR]: failed to loar local connector");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PostInitialise()
|
public void PostInitialise()
|
||||||
{
|
{
|
||||||
if (m_LocalGridService != null)
|
|
||||||
((ISharedRegionModule)m_LocalGridService).PostInitialise();
|
((ISharedRegionModule)m_LocalGridService).PostInitialise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,13 +139,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
if (m_Enabled)
|
if (m_Enabled)
|
||||||
scene.RegisterModuleInterface<IGridService>(this);
|
scene.RegisterModuleInterface<IGridService>(this);
|
||||||
|
|
||||||
if (m_LocalGridService != null)
|
|
||||||
((ISharedRegionModule)m_LocalGridService).AddRegion(scene);
|
((ISharedRegionModule)m_LocalGridService).AddRegion(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveRegion(Scene scene)
|
public void RemoveRegion(Scene scene)
|
||||||
{
|
{
|
||||||
if (m_LocalGridService != null)
|
|
||||||
((ISharedRegionModule)m_LocalGridService).RemoveRegion(scene);
|
((ISharedRegionModule)m_LocalGridService).RemoveRegion(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,15 +180,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
|
|
||||||
public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
|
public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
|
||||||
{
|
{
|
||||||
bool inCache = false;
|
GridRegion rinfo = m_LocalGridService.GetRegionByUUID(scopeID, regionID);
|
||||||
GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionID,out inCache);
|
if (rinfo != null)
|
||||||
if (inCache)
|
|
||||||
return rinfo;
|
return rinfo;
|
||||||
|
|
||||||
rinfo = m_LocalGridService.GetRegionByUUID(scopeID, regionID);
|
|
||||||
if (rinfo == null)
|
|
||||||
rinfo = m_RemoteGridService.GetRegionByUUID(scopeID, regionID);
|
rinfo = m_RemoteGridService.GetRegionByUUID(scopeID, regionID);
|
||||||
|
|
||||||
m_RegionInfoCache.Cache(scopeID, rinfo);
|
m_RegionInfoCache.Cache(scopeID, rinfo);
|
||||||
return rinfo;
|
return rinfo;
|
||||||
}
|
}
|
||||||
|
@ -193,25 +195,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
// The coordinates are world coords (meters), NOT region units.
|
// The coordinates are world coords (meters), NOT region units.
|
||||||
public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
|
public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
|
||||||
{
|
{
|
||||||
// try in cache by handler first
|
GridRegion rinfo = m_LocalGridService.GetRegionByPosition(scopeID, x, y);
|
||||||
ulong regionHandle = Util.RegionWorldLocToHandle((uint)x, (uint)y);
|
if (rinfo != null)
|
||||||
|
{
|
||||||
bool inCache = false;
|
m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Added region {0} to the cache from local. Pos=<{1},{2}>, RegionHandle={3}",
|
||||||
GridRegion rinfo = m_RegionInfoCache.Get(scopeID, regionHandle, out inCache);
|
rinfo.RegionName, rinfo.RegionCoordX, rinfo.RegionCoordY, rinfo.RegionHandle);
|
||||||
if (inCache)
|
|
||||||
return rinfo;
|
return rinfo;
|
||||||
|
}
|
||||||
|
|
||||||
// try in cache by slower position next
|
|
||||||
rinfo = m_RegionInfoCache.Get(scopeID, x, y, out inCache);
|
|
||||||
if (inCache)
|
|
||||||
return rinfo;
|
|
||||||
|
|
||||||
rinfo = m_LocalGridService.GetRegionByPosition(scopeID, x, y);
|
|
||||||
if (rinfo == null)
|
|
||||||
rinfo = m_RemoteGridService.GetRegionByPosition(scopeID, x, y);
|
rinfo = m_RemoteGridService.GetRegionByPosition(scopeID, x, y);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (rinfo == null)
|
if (rinfo == null)
|
||||||
{
|
{
|
||||||
uint regionX = Util.WorldToRegionLoc((uint)x);
|
uint regionX = Util.WorldToRegionLoc((uint)x);
|
||||||
|
@ -223,23 +216,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
||||||
m_RegionInfoCache.Cache(scopeID, rinfo);
|
m_RegionInfoCache.Cache(scopeID, rinfo);
|
||||||
|
|
||||||
m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Added region {0} to the cache. Pos=<{1},{2}>, RegionHandle={3}",
|
m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Added region {0} to the cache. Pos=<{1},{2}>, RegionHandle={3}",
|
||||||
rinfo.RegionName, rinfo.RegionCoordX, rinfo.RegionCoordY, (rinfo == null) ? regionHandle : rinfo.RegionHandle);
|
rinfo.RegionName, rinfo.RegionCoordX, rinfo.RegionCoordY, rinfo.RegionHandle);
|
||||||
}
|
}
|
||||||
return rinfo;
|
return rinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GridRegion GetRegionByName(UUID scopeID, string regionName)
|
public GridRegion GetRegionByName(UUID scopeID, string regionName)
|
||||||
{
|
{
|
||||||
bool inCache = false;
|
GridRegion rinfo = m_LocalGridService.GetRegionByName(scopeID, regionName);
|
||||||
GridRegion rinfo = m_RegionInfoCache.Get(scopeID, regionName, out inCache);
|
if (rinfo != null)
|
||||||
if (inCache)
|
|
||||||
return rinfo;
|
return rinfo;
|
||||||
|
|
||||||
rinfo = m_LocalGridService.GetRegionByName(scopeID, regionName);
|
|
||||||
if (rinfo == null)
|
|
||||||
rinfo = m_RemoteGridService.GetRegionByName(scopeID, regionName);
|
rinfo = m_RemoteGridService.GetRegionByName(scopeID, regionName);
|
||||||
|
|
||||||
// can't cache negative results for name lookups
|
|
||||||
m_RegionInfoCache.Cache(scopeID, rinfo);
|
m_RegionInfoCache.Cache(scopeID, rinfo);
|
||||||
return rinfo;
|
return rinfo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
|
||||||
config.Configs["GridService"].Set("Region_Test_Region_3", "FallbackRegion");
|
config.Configs["GridService"].Set("Region_Test_Region_3", "FallbackRegion");
|
||||||
config.Configs["GridService"].Set("Region_Other_Region_4", "FallbackRegion");
|
config.Configs["GridService"].Set("Region_Other_Region_4", "FallbackRegion");
|
||||||
|
|
||||||
m_LocalConnector = new LocalGridServicesConnector(config);
|
m_LocalConnector = new LocalGridServicesConnector(config, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -31,21 +31,6 @@
|
||||||
SimulationServiceInConnector = true
|
SimulationServiceInConnector = true
|
||||||
LibraryModule = true
|
LibraryModule = true
|
||||||
|
|
||||||
[SimulationService]
|
|
||||||
; This is the protocol version which the simulator advertises to the source destination when acting as a target destination for a teleport
|
|
||||||
; It is used to control the teleport handoff process.
|
|
||||||
; Valid values are
|
|
||||||
; "SIMULATION/0.3"
|
|
||||||
; - This is the default, and it supports teleports to variable-sized regions
|
|
||||||
; - Older versions can teleport to this one, but only if the destination region
|
|
||||||
; is 256x256
|
|
||||||
; "SIMULATION/0.2"
|
|
||||||
; - A source simulator which only implements "SIMULATION/0.1" can still teleport with that protocol
|
|
||||||
; - this protocol is more efficient than "SIMULATION/0.1"
|
|
||||||
; "SIMULATION/0.1"
|
|
||||||
; - this is an older teleport protocol used in OpenSimulator 0.7.5 and before.
|
|
||||||
ConnectorProtocolVersion = "SIMULATION/0.3"
|
|
||||||
|
|
||||||
[SimulationDataStore]
|
[SimulationDataStore]
|
||||||
LocalServiceModule = "OpenSim.Services.SimulationService.dll:SimulationDataService"
|
LocalServiceModule = "OpenSim.Services.SimulationService.dll:SimulationDataService"
|
||||||
|
|
||||||
|
|
|
@ -36,21 +36,6 @@
|
||||||
SimulationServiceInConnector = true
|
SimulationServiceInConnector = true
|
||||||
LibraryModule = true
|
LibraryModule = true
|
||||||
|
|
||||||
[SimulationService]
|
|
||||||
; This is the protocol version which the simulator advertises to the source destination when acting as a target destination for a teleport
|
|
||||||
; It is used to control the teleport handoff process.
|
|
||||||
; Valid values are
|
|
||||||
; "SIMULATION/0.3"
|
|
||||||
; - This is the default, and it supports teleports to variable-sized regions
|
|
||||||
; - Older versions can teleport to this one, but only if the destination region
|
|
||||||
; is 256x256
|
|
||||||
; "SIMULATION/0.2"
|
|
||||||
; - A source simulator which only implements "SIMULATION/0.1" can still teleport with that protocol
|
|
||||||
; - this protocol is more efficient than "SIMULATION/0.1"
|
|
||||||
; "SIMULATION/0.1"
|
|
||||||
; - this is an older teleport protocol used in OpenSimulator 0.7.5 and before.
|
|
||||||
ConnectorProtocolVersion = "SIMULATION/0.3"
|
|
||||||
|
|
||||||
[Profile]
|
[Profile]
|
||||||
Module = "BasicProfileModule"
|
Module = "BasicProfileModule"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue