aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs125
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs103
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs133
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs80
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs2
5 files changed, 178 insertions, 265 deletions
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
index e585c25..58bd4ea 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
51 private static string LogHeader = "[LOCAL GRID SERVICE CONNECTOR]"; 51 private static string LogHeader = "[LOCAL GRID SERVICE CONNECTOR]";
52 52
53 private IGridService m_GridService; 53 private IGridService m_GridService;
54 private Dictionary<UUID, RegionCache> m_LocalCache = new Dictionary<UUID, RegionCache>(); 54 private RegionInfoCache m_RegionInfoCache = null;
55 55
56 private bool m_Enabled; 56 private bool m_Enabled;
57 57
@@ -60,10 +60,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
60 m_log.DebugFormat("{0} LocalGridServicesConnector no parms.", LogHeader); 60 m_log.DebugFormat("{0} LocalGridServicesConnector no parms.", LogHeader);
61 } 61 }
62 62
63 public LocalGridServicesConnector(IConfigSource source) 63 public LocalGridServicesConnector(IConfigSource source, RegionInfoCache regionInfoCache)
64 { 64 {
65 m_log.DebugFormat("{0} LocalGridServicesConnector instantiated directly.", LogHeader); 65 m_log.DebugFormat("{0} LocalGridServicesConnector instantiated directly.", LogHeader);
66 InitialiseService(source); 66 InitialiseService(source, regionInfoCache);
67 } 67 }
68 68
69 #region ISharedRegionModule 69 #region ISharedRegionModule
@@ -86,19 +86,25 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
86 string name = moduleConfig.GetString("GridServices", ""); 86 string name = moduleConfig.GetString("GridServices", "");
87 if (name == Name) 87 if (name == Name)
88 { 88 {
89 InitialiseService(source); 89
90 m_log.Info("[LOCAL GRID SERVICE CONNECTOR]: Local grid connector enabled"); 90 if(InitialiseService(source,null))
91 m_log.Info("[LOCAL GRID SERVICE CONNECTOR]: Local grid connector enabled");
91 } 92 }
92 } 93 }
93 } 94 }
94 95
95 private void InitialiseService(IConfigSource source) 96 private bool InitialiseService(IConfigSource source, RegionInfoCache ric)
96 { 97 {
98 if(ric == null)
99 m_RegionInfoCache = new RegionInfoCache();
100 else
101 m_RegionInfoCache = ric;
102
97 IConfig config = source.Configs["GridService"]; 103 IConfig config = source.Configs["GridService"];
98 if (config == null) 104 if (config == null)
99 { 105 {
100 m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: GridService missing from OpenSim.ini"); 106 m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: GridService missing from OpenSim.ini");
101 return; 107 return false;
102 } 108 }
103 109
104 string serviceDll = config.GetString("LocalServiceModule", String.Empty); 110 string serviceDll = config.GetString("LocalServiceModule", String.Empty);
@@ -106,7 +112,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
106 if (serviceDll == String.Empty) 112 if (serviceDll == String.Empty)
107 { 113 {
108 m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: No LocalServiceModule named in section GridService"); 114 m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: No LocalServiceModule named in section GridService");
109 return; 115 return false;
110 } 116 }
111 117
112 Object[] args = new Object[] { source }; 118 Object[] args = new Object[] { source };
@@ -117,10 +123,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
117 if (m_GridService == null) 123 if (m_GridService == null)
118 { 124 {
119 m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: Can't load grid service"); 125 m_log.Error("[LOCAL GRID SERVICE CONNECTOR]: Can't load grid service");
120 return; 126 return false;
121 } 127 }
122 128
123 m_Enabled = true; 129 m_Enabled = true;
130 return true;
124 } 131 }
125 132
126 public void PostInitialise() 133 public void PostInitialise()
@@ -143,13 +150,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
143 150
144 scene.RegisterModuleInterface<IGridService>(this); 151 scene.RegisterModuleInterface<IGridService>(this);
145 152
146 lock (m_LocalCache) 153 m_RegionInfoCache.CacheLocal(new GridRegion(scene.RegionInfo));
147 { 154 scene.EventManager.OnRegionUp += OnRegionUp;
148 if (m_LocalCache.ContainsKey(scene.RegionInfo.RegionID))
149 m_log.ErrorFormat("[LOCAL GRID SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!");
150 else
151 m_LocalCache.Add(scene.RegionInfo.RegionID, new RegionCache(scene));
152 }
153 } 155 }
154 156
155 public void RemoveRegion(Scene scene) 157 public void RemoveRegion(Scene scene)
@@ -157,11 +159,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
157 if (!m_Enabled) 159 if (!m_Enabled)
158 return; 160 return;
159 161
160 lock (m_LocalCache) 162 m_RegionInfoCache.Remove(scene.RegionInfo.ScopeID, scene.RegionInfo.RegionID);
161 { 163 scene.EventManager.OnRegionUp -= OnRegionUp;
162 m_LocalCache[scene.RegionInfo.RegionID].Clear();
163 m_LocalCache.Remove(scene.RegionInfo.RegionID);
164 }
165 } 164 }
166 165
167 public void RegionLoaded(Scene scene) 166 public void RegionLoaded(Scene scene)
@@ -172,6 +171,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
172 171
173 #region IGridService 172 #region IGridService
174 173
174 private void OnRegionUp(GridRegion region)
175 {
176 // This shouldn't happen
177 if (region == null)
178 return;
179
180 m_RegionInfoCache.CacheNearNeighbour(region.ScopeID, region);
181 }
182
175 public string RegisterRegion(UUID scopeID, GridRegion regionInfo) 183 public string RegisterRegion(UUID scopeID, GridRegion regionInfo)
176 { 184 {
177 return m_GridService.RegisterRegion(scopeID, regionInfo); 185 return m_GridService.RegisterRegion(scopeID, regionInfo);
@@ -189,7 +197,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
189 197
190 public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID) 198 public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
191 { 199 {
192 return m_GridService.GetRegionByUUID(scopeID, regionID); 200 bool inCache = false;
201 GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionID,out inCache);
202 if (inCache)
203 return rinfo;
204
205 rinfo = m_GridService.GetRegionByUUID(scopeID, regionID);
206 if(rinfo != null)
207 m_RegionInfoCache.Cache(scopeID, rinfo);
208 return rinfo;
193 } 209 }
194 210
195 // Get a region given its base coordinates. 211 // Get a region given its base coordinates.
@@ -197,52 +213,37 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
197 // be the base coordinate of the region. 213 // be the base coordinate of the region.
198 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) 214 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
199 { 215 {
200 GridRegion region = null; 216 // try in cache by handler first
201 uint regionX = Util.WorldToRegionLoc((uint)x); 217 ulong regionHandle = Util.RegionWorldLocToHandle((uint)x, (uint)y);
202 uint regionY = Util.WorldToRegionLoc((uint)y);
203 218
204 // First see if it's a neighbour, even if it isn't on this sim. 219 bool inCache = false;
205 // Neighbour data is cached in memory, so this is fast 220 GridRegion rinfo = m_RegionInfoCache.Get(scopeID, regionHandle, out inCache);
221 if (inCache)
222 return rinfo;
206 223
207 lock (m_LocalCache) 224 // try in cache by slower position next
208 { 225 rinfo = m_RegionInfoCache.Get(scopeID, x, y, out inCache);
209 foreach (RegionCache rcache in m_LocalCache.Values) 226 if (inCache)
210 { 227 return rinfo;
211 region = rcache.GetRegionByPosition(x, y);
212 if (region != null)
213 {
214 //m_log.DebugFormat("{0} GetRegionByPosition. Found region {1} in cache (of region {2}). Pos=<{3},{4}>",
215 // LogHeader, region.RegionName, rcache.RegionName,
216 // Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY));
217 break;
218 }
219 }
220 }
221 228
222 // Then try on this sim (may be a lookup in DB if this is using MySql). 229 // Then try on this sim (may be a lookup in DB if this is using MySql).
223 if (region == null) 230 rinfo = m_GridService.GetRegionByPosition(scopeID, x, y);
224 { 231 if(rinfo != null)
225 region = m_GridService.GetRegionByPosition(scopeID, x, y); 232 m_RegionInfoCache.Cache(scopeID, rinfo);
226 233 return rinfo;
227 if (region == null)
228 {
229 m_log.DebugFormat("{0} GetRegionByPosition. Region not found by grid service. Pos=<{1},{2}>",
230 LogHeader, regionX, regionY);
231 }
232 else
233 {
234 m_log.DebugFormat("{0} GetRegionByPosition. Got region {1} from grid service. Pos=<{2},{3}>",
235 LogHeader, region.RegionName,
236 Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY));
237 }
238 }
239
240 return region;
241 } 234 }
242 235
243 public GridRegion GetRegionByName(UUID scopeID, string regionName) 236 public GridRegion GetRegionByName(UUID scopeID, string regionName)
244 { 237 {
245 return m_GridService.GetRegionByName(scopeID, regionName); 238 bool inCache = false;
239 GridRegion rinfo = m_RegionInfoCache.Get(scopeID, regionName, out inCache);
240 if (inCache)
241 return rinfo;
242
243 rinfo = m_GridService.GetRegionByName(scopeID, regionName);
244 if(rinfo != null)
245 m_RegionInfoCache.Cache(scopeID, rinfo);
246 return rinfo;
246 } 247 }
247 248
248 public List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber) 249 public List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber)
@@ -290,7 +291,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
290 public void HandleShowNeighboursCommand(string module, string[] cmdparams) 291 public void HandleShowNeighboursCommand(string module, string[] cmdparams)
291 { 292 {
292 System.Text.StringBuilder caps = new System.Text.StringBuilder(); 293 System.Text.StringBuilder caps = new System.Text.StringBuilder();
293 294/* temporary broken
294 lock (m_LocalCache) 295 lock (m_LocalCache)
295 { 296 {
296 foreach (KeyValuePair<UUID, RegionCache> kvp in m_LocalCache) 297 foreach (KeyValuePair<UUID, RegionCache> kvp in m_LocalCache)
@@ -303,6 +304,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
303 } 304 }
304 305
305 MainConsole.Instance.Output(caps.ToString()); 306 MainConsole.Instance.Output(caps.ToString());
307*/
308 MainConsole.Instance.Output("Neighbours list not avaiable in this version\n");
306 } 309 }
307 } 310 }
308} 311}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs
deleted file mode 100644
index 2961c10..0000000
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs
+++ /dev/null
@@ -1,103 +0,0 @@
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 OpenSimulator 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
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31
32using OpenSim.Framework;
33using OpenSim.Region.Framework.Scenes;
34using OpenSim.Services.Interfaces;
35using GridRegion = OpenSim.Services.Interfaces.GridRegion;
36
37using OpenMetaverse;
38using log4net;
39
40namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
41{
42 public class RegionCache
43 {
44 private static readonly ILog m_log =
45 LogManager.GetLogger(
46 MethodBase.GetCurrentMethod().DeclaringType);
47
48 private Scene m_scene;
49 private Dictionary<ulong, GridRegion> m_neighbours = new Dictionary<ulong, GridRegion>();
50
51 public string RegionName
52 {
53 get { return m_scene.RegionInfo.RegionName; }
54 }
55
56 public RegionCache(Scene s)
57 {
58 m_scene = s;
59 m_scene.EventManager.OnRegionUp += OnRegionUp;
60 }
61
62 private void OnRegionUp(GridRegion otherRegion)
63 {
64 // This shouldn't happen
65 if (otherRegion == null)
66 return;
67
68 m_log.DebugFormat("[REGION CACHE]: (on region {0}) Region {1} is up @ {2}-{3}",
69 m_scene.RegionInfo.RegionName, otherRegion.RegionName, Util.WorldToRegionLoc((uint)otherRegion.RegionLocX), Util.WorldToRegionLoc((uint)otherRegion.RegionLocY));
70
71 m_neighbours[otherRegion.RegionHandle] = otherRegion;
72 }
73
74 public void Clear()
75 {
76 m_scene.EventManager.OnRegionUp -= OnRegionUp;
77 m_neighbours.Clear();
78 }
79
80 public List<GridRegion> GetNeighbours()
81 {
82 return new List<GridRegion>(m_neighbours.Values);
83 }
84
85 public GridRegion GetRegionByPosition(int x, int y)
86 {
87 // do actual search by position
88 // not the best, but this will not hold that many regions
89 GridRegion foundRegion = null;
90 foreach(GridRegion r in m_neighbours.Values)
91 {
92 if (x >= r.RegionLocX && x < r.RegionLocX + r.RegionSizeX
93 && y >= r.RegionLocY && y < r.RegionLocY + r.RegionSizeY)
94 {
95 foundRegion = r;
96 break;
97 }
98 }
99
100 return foundRegion;
101 }
102 }
103}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs
index ffe3fab..8f3dfc1 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs
@@ -59,26 +59,42 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
59 59
60 public void Cache(UUID scopeID, GridRegion rinfo) 60 public void Cache(UUID scopeID, GridRegion rinfo)
61 { 61 {
62 // for now, do not cache negative results; this is because
63 // we need to figure out how to handle regions coming online
64 // in a timely way
65 if (rinfo == null) 62 if (rinfo == null)
66 return; 63 return;
67 64
68 m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS); 65 m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS);
69 } 66 }
70 67
68 public void CacheLocal(GridRegion rinfo)
69 {
70 if (rinfo == null)
71 return;
72
73 m_Cache.AddOrUpdate(rinfo.ScopeID, rinfo, 1e7f);
74 }
75
76 public void CacheNearNeighbour(UUID scopeID, GridRegion rinfo)
77 {
78 if (rinfo == null)
79 return;
80
81// m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS);
82 m_Cache.Add(scopeID, rinfo, CACHE_EXPIRATION_SECONDS); // don't override local regions
83 }
84
71 public void Cache(UUID scopeID, GridRegion rinfo, float expireSeconds) 85 public void Cache(UUID scopeID, GridRegion rinfo, float expireSeconds)
72 { 86 {
73 // for now, do not cache negative results; this is because
74 // we need to figure out how to handle regions coming online
75 // in a timely way
76 if (rinfo == null) 87 if (rinfo == null)
77 return; 88 return;
78 89
79 m_Cache.AddOrUpdate(scopeID, rinfo, expireSeconds); 90 m_Cache.AddOrUpdate(scopeID, rinfo, expireSeconds);
80 } 91 }
81 92
93 public void Remove(UUID scopeID, UUID regionID)
94 {
95 m_Cache.Remove(scopeID, regionID);
96 }
97
82 public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache) 98 public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache)
83 { 99 {
84 inCache = false; 100 inCache = false;
@@ -134,43 +150,47 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
134 150
135 return null; 151 return null;
136 } 152 }
137
138 } 153 }
139 154
140 155
141 // following code partialy adapted from lib OpenMetaverse 156 // following code partialy adapted from lib OpenMetaverse
142 public class RegionKey : IComparable<RegionKey> 157 public class RegionKey
143 { 158 {
144 private UUID m_scopeID; 159 public UUID ScopeID;
145 private UUID m_RegionID; 160 public UUID RegionID;
146 private DateTime m_expirationDate;
147 161
148 public RegionKey(UUID scopeID, UUID id) 162 public RegionKey(UUID scopeID, UUID id)
149 { 163 {
150 m_scopeID = scopeID; 164 ScopeID = scopeID;
151 m_RegionID = id; 165 RegionID = id;
152 } 166 }
153 167
154 public UUID ScopeID 168 public override int GetHashCode()
155 { 169 {
156 get { return m_scopeID; } 170 int hash = ScopeID.GetHashCode();
171 hash += hash * 23 + RegionID.GetHashCode();
172 return hash;
157 } 173 }
158 public DateTime ExpirationDate 174
175 public override bool Equals(Object b)
159 { 176 {
160 get { return m_expirationDate; } 177 if(b == null)
161 set { m_expirationDate = value; } 178 return false;
179 RegionKey kb = b as RegionKey;
180 return (ScopeID == kb.ScopeID && RegionID == kb.RegionID);
162 } 181 }
182 }
163 183
164 public int GetHaskCode() 184 class RegionKeyEqual : EqualityComparer<RegionKey>
185 {
186 public override int GetHashCode(RegionKey rk)
165 { 187 {
166 int hash = m_scopeID.GetHashCode(); 188 return rk.GetHashCode();
167 hash += hash * 23 + m_RegionID.GetHashCode();
168 return hash;
169 } 189 }
170 190
171 public int CompareTo(RegionKey other) 191 public override bool Equals(RegionKey a, RegionKey b)
172 { 192 {
173 return GetHashCode().CompareTo(other.GetHashCode()); 193 return (a.ScopeID == b.ScopeID && a.RegionID == b.RegionID);
174 } 194 }
175 } 195 }
176 196
@@ -246,7 +266,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
246 } 266 }
247 } 267 }
248 268
249 public sealed class RegionsExpiringCache 269 public class RegionsExpiringCache
250 { 270 {
251 const double CACHE_PURGE_HZ = 60; // seconds 271 const double CACHE_PURGE_HZ = 60; // seconds
252 const int MAX_LOCK_WAIT = 10000; // milliseconds 272 const int MAX_LOCK_WAIT = 10000; // milliseconds
@@ -256,7 +276,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
256 /// <summary>For thread safety</summary> 276 /// <summary>For thread safety</summary>
257 object isPurging = new object(); 277 object isPurging = new object();
258 278
259 Dictionary<RegionKey, GridRegion> timedStorage = new Dictionary<RegionKey, GridRegion>(); 279 static RegionKeyEqual keyequal = new RegionKeyEqual();
280 Dictionary<RegionKey, GridRegion> timedStorage = new Dictionary<RegionKey, GridRegion>(keyequal);
281 Dictionary<RegionKey, DateTime> timedExpires = new Dictionary<RegionKey, DateTime>();
260 Dictionary<UUID, RegionInfoByScope> InfobyScope = new Dictionary<UUID, RegionInfoByScope>(); 282 Dictionary<UUID, RegionInfoByScope> InfobyScope = new Dictionary<UUID, RegionInfoByScope>();
261 private System.Timers.Timer timer = new System.Timers.Timer(TimeSpan.FromSeconds(CACHE_PURGE_HZ).TotalMilliseconds); 283 private System.Timers.Timer timer = new System.Timers.Timer(TimeSpan.FromSeconds(CACHE_PURGE_HZ).TotalMilliseconds);
262 284
@@ -278,8 +300,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
278 if (timedStorage.ContainsKey(key)) 300 if (timedStorage.ContainsKey(key))
279 return false; 301 return false;
280 302
281 key.ExpirationDate = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds); 303 DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
282 timedStorage.Add(key, region); 304 timedStorage[key] = region;
305 timedExpires[key] = expire;
283 306
284 RegionInfoByScope ris = null; 307 RegionInfoByScope ris = null;
285 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null) 308 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
@@ -303,12 +326,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
303 try 326 try
304 { 327 {
305 RegionKey key = new RegionKey(scope, region.RegionID); 328 RegionKey key = new RegionKey(scope, region.RegionID);
306 key.ExpirationDate = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds); 329 DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
307 330
308 if (timedStorage.ContainsKey(key)) 331 if (timedStorage.ContainsKey(key))
309 { 332 {
310 timedStorage.Remove(key); 333 timedStorage[key] = region;
311 timedStorage.Add(key, region); 334 if(expire > timedExpires[key])
335 timedExpires[key] = expire;
312 336
313 if(!InfobyScope.ContainsKey(scope)) 337 if(!InfobyScope.ContainsKey(scope))
314 { 338 {
@@ -319,7 +343,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
319 } 343 }
320 else 344 else
321 { 345 {
322 timedStorage.Add(key, region); 346 timedStorage[key] = region;
347 timedExpires[key] = expire;
323 RegionInfoByScope ris = null; 348 RegionInfoByScope ris = null;
324 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null) 349 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
325 { 350 {
@@ -341,6 +366,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
341 try 366 try
342 { 367 {
343 timedStorage.Clear(); 368 timedStorage.Clear();
369 timedExpires.Clear();
344 InfobyScope.Clear(); 370 InfobyScope.Clear();
345 } 371 }
346 finally { Monitor.Exit(syncRoot); } 372 finally { Monitor.Exit(syncRoot); }
@@ -370,10 +396,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
370 return timedStorage.Count; 396 return timedStorage.Count;
371 } 397 }
372 } 398 }
373
374 public bool Remove(UUID scope, GridRegion region) 399 public bool Remove(UUID scope, GridRegion region)
375 { 400 {
376 RegionKey key = new RegionKey(scope, region.RegionID); 401 return Remove(scope, region.RegionID);
402 }
403 public bool Remove(UUID scope, UUID regionID)
404 {
405 RegionKey key = new RegionKey(scope, regionID);
377 406
378 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) 407 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
379 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); 408 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
@@ -391,6 +420,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
391 InfobyScope.Remove(scope); 420 InfobyScope.Remove(scope);
392 } 421 }
393 timedStorage.Remove(key); 422 timedStorage.Remove(key);
423 timedExpires.Remove(key);
394 return true; 424 return true;
395 } 425 }
396 else 426 else
@@ -544,9 +574,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
544 if (!timedStorage.ContainsKey(key)) 574 if (!timedStorage.ContainsKey(key))
545 return false; 575 return false;
546 576
547 timedStorage.Remove(key); 577 DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
548 key.ExpirationDate = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds); 578 timedStorage[key] = region;
549 timedStorage.Add(key, region); 579 if(expire > timedExpires[key])
580 timedExpires[key] = expire;
581
550 return true; 582 return true;
551 } 583 }
552 finally { Monitor.Exit(syncRoot); } 584 finally { Monitor.Exit(syncRoot); }
@@ -572,26 +604,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
572 return; 604 return;
573 try 605 try
574 { 606 {
575 OpenMetaverse.Lazy<List<object>> expiredItems = new OpenMetaverse.Lazy<List<object>>(); 607 List<RegionKey> expiredkeys = new List<RegionKey>();
576 608
577 foreach (RegionKey timedKey in timedStorage.Keys) 609 foreach (KeyValuePair<RegionKey, DateTime> kvp in timedExpires)
578 { 610 {
579 if (timedKey.ExpirationDate < signalTime) 611 if (kvp.Value < signalTime)
580 { 612 expiredkeys.Add(kvp.Key);
581 // Mark the object for purge
582 expiredItems.Value.Add(timedKey);
583 }
584 else
585 {
586 break;
587 }
588 } 613 }
589 614
590 615 if (expiredkeys.Count > 0)
591 RegionInfoByScope ris;
592 if (expiredItems.IsValueCreated)
593 { 616 {
594 foreach (RegionKey key in expiredItems.Value) 617 RegionInfoByScope ris;
618 foreach (RegionKey key in expiredkeys)
595 { 619 {
596 ris = null; 620 ris = null;
597 if(InfobyScope.TryGetValue(key.ScopeID, out ris) && ris != null) 621 if(InfobyScope.TryGetValue(key.ScopeID, out ris) && ris != null)
@@ -604,6 +628,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
604 InfobyScope.Remove(key.ScopeID); 628 InfobyScope.Remove(key.ScopeID);
605 } 629 }
606 timedStorage.Remove(key); 630 timedStorage.Remove(key);
631 timedExpires.Remove(key);
607 } 632 }
608 } 633 }
609 } 634 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
index 6575cfd..363adde 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
@@ -87,39 +87,47 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
87 string name = moduleConfig.GetString("GridServices", ""); 87 string name = moduleConfig.GetString("GridServices", "");
88 if (name == Name) 88 if (name == Name)
89 { 89 {
90 InitialiseServices(source); 90 if(InitialiseServices(source))
91 m_Enabled = true; 91 {
92 m_log.Info("[REMOTE GRID CONNECTOR]: Remote grid enabled"); 92 m_Enabled = true;
93 m_log.Info("[REMOTE GRID CONNECTOR]: Remote grid enabled");
94 }
93 } 95 }
94 } 96 }
95 } 97 }
96 98
97 private void InitialiseServices(IConfigSource source) 99 private bool InitialiseServices(IConfigSource source)
98 { 100 {
99 IConfig gridConfig = source.Configs["GridService"]; 101 IConfig gridConfig = source.Configs["GridService"];
100 if (gridConfig == null) 102 if (gridConfig == null)
101 { 103 {
102 m_log.Error("[REMOTE GRID CONNECTOR]: GridService missing from OpenSim.ini"); 104 m_log.Error("[REMOTE GRID CONNECTOR]: GridService missing from OpenSim.ini");
103 return; 105 return false;
104 } 106 }
105 107
106 string networkConnector = gridConfig.GetString("NetworkConnector", string.Empty); 108 string networkConnector = gridConfig.GetString("NetworkConnector", string.Empty);
107 if (networkConnector == string.Empty) 109 if (networkConnector == string.Empty)
108 { 110 {
109 m_log.Error("[REMOTE GRID CONNECTOR]: Please specify a network connector under [GridService]"); 111 m_log.Error("[REMOTE GRID CONNECTOR]: Please specify a network connector under [GridService]");
110 return; 112 return false;
111 } 113 }
112 114
113 Object[] args = new Object[] { source }; 115 Object[] args = new Object[] { source };
114 m_RemoteGridService = ServerUtils.LoadPlugin<IGridService>(networkConnector, args); 116 m_RemoteGridService = ServerUtils.LoadPlugin<IGridService>(networkConnector, args);
115 117
116 m_LocalGridService = new LocalGridServicesConnector(source); 118 m_LocalGridService = new LocalGridServicesConnector(source, m_RegionInfoCache);
119 if (m_LocalGridService == null)
120 {
121 m_log.Error("[REMOTE GRID CONNECTOR]: failed to loar local connector");
122 return false;
123 }
124
125 return true;
117 } 126 }
118 127
119 public void PostInitialise() 128 public void PostInitialise()
120 { 129 {
121 if (m_LocalGridService != null) 130 ((ISharedRegionModule)m_LocalGridService).PostInitialise();
122 ((ISharedRegionModule)m_LocalGridService).PostInitialise();
123 } 131 }
124 132
125 public void Close() 133 public void Close()
@@ -131,14 +139,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
131 if (m_Enabled) 139 if (m_Enabled)
132 scene.RegisterModuleInterface<IGridService>(this); 140 scene.RegisterModuleInterface<IGridService>(this);
133 141
134 if (m_LocalGridService != null) 142 ((ISharedRegionModule)m_LocalGridService).AddRegion(scene);
135 ((ISharedRegionModule)m_LocalGridService).AddRegion(scene);
136 } 143 }
137 144
138 public void RemoveRegion(Scene scene) 145 public void RemoveRegion(Scene scene)
139 { 146 {
140 if (m_LocalGridService != null) 147 ((ISharedRegionModule)m_LocalGridService).RemoveRegion(scene);
141 ((ISharedRegionModule)m_LocalGridService).RemoveRegion(scene);
142 } 148 }
143 149
144 public void RegionLoaded(Scene scene) 150 public void RegionLoaded(Scene scene)
@@ -174,15 +180,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
174 180
175 public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID) 181 public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
176 { 182 {
177 bool inCache = false; 183 GridRegion rinfo = m_LocalGridService.GetRegionByUUID(scopeID, regionID);
178 GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionID,out inCache); 184 if (rinfo != null)
179 if (inCache)
180 return rinfo; 185 return rinfo;
181
182 rinfo = m_LocalGridService.GetRegionByUUID(scopeID, regionID);
183 if (rinfo == null)
184 rinfo = m_RemoteGridService.GetRegionByUUID(scopeID, regionID);
185 186
187 rinfo = m_RemoteGridService.GetRegionByUUID(scopeID, regionID);
186 m_RegionInfoCache.Cache(scopeID, rinfo); 188 m_RegionInfoCache.Cache(scopeID, rinfo);
187 return rinfo; 189 return rinfo;
188 } 190 }
@@ -193,24 +195,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
193 // The coordinates are world coords (meters), NOT region units. 195 // The coordinates are world coords (meters), NOT region units.
194 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) 196 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
195 { 197 {
196 // try in cache by handler first 198 GridRegion rinfo = m_LocalGridService.GetRegionByPosition(scopeID, x, y);
197 ulong regionHandle = Util.RegionWorldLocToHandle((uint)x, (uint)y); 199 if (rinfo != null)
198 200 {
199 bool inCache = false; 201 m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Added region {0} to the cache from local. Pos=<{1},{2}>, RegionHandle={3}",
200 GridRegion rinfo = m_RegionInfoCache.Get(scopeID, regionHandle, out inCache); 202 rinfo.RegionName, rinfo.RegionCoordX, rinfo.RegionCoordY, rinfo.RegionHandle);
201 if (inCache)
202 return rinfo;
203
204 // try in cache by slower position next
205 rinfo = m_RegionInfoCache.Get(scopeID, x, y, out inCache);
206 if (inCache)
207 return rinfo; 203 return rinfo;
204 }
208 205
209 rinfo = m_LocalGridService.GetRegionByPosition(scopeID, x, y); 206 rinfo = m_RemoteGridService.GetRegionByPosition(scopeID, x, y);
210 if (rinfo == null)
211 rinfo = m_RemoteGridService.GetRegionByPosition(scopeID, x, y);
212
213
214 207
215 if (rinfo == null) 208 if (rinfo == null)
216 { 209 {
@@ -223,23 +216,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
223 m_RegionInfoCache.Cache(scopeID, rinfo); 216 m_RegionInfoCache.Cache(scopeID, rinfo);
224 217
225 m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Added region {0} to the cache. Pos=<{1},{2}>, RegionHandle={3}", 218 m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Added region {0} to the cache. Pos=<{1},{2}>, RegionHandle={3}",
226 rinfo.RegionName, rinfo.RegionCoordX, rinfo.RegionCoordY, (rinfo == null) ? regionHandle : rinfo.RegionHandle); 219 rinfo.RegionName, rinfo.RegionCoordX, rinfo.RegionCoordY, rinfo.RegionHandle);
227 } 220 }
228 return rinfo; 221 return rinfo;
229 } 222 }
230 223
231 public GridRegion GetRegionByName(UUID scopeID, string regionName) 224 public GridRegion GetRegionByName(UUID scopeID, string regionName)
232 { 225 {
233 bool inCache = false; 226 GridRegion rinfo = m_LocalGridService.GetRegionByName(scopeID, regionName);
234 GridRegion rinfo = m_RegionInfoCache.Get(scopeID, regionName, out inCache); 227 if (rinfo != null)
235 if (inCache)
236 return rinfo; 228 return rinfo;
237 229
238 rinfo = m_LocalGridService.GetRegionByName(scopeID, regionName); 230 rinfo = m_RemoteGridService.GetRegionByName(scopeID, regionName);
239 if (rinfo == null)
240 rinfo = m_RemoteGridService.GetRegionByName(scopeID, regionName);
241
242 // can't cache negative results for name lookups
243 m_RegionInfoCache.Cache(scopeID, rinfo); 231 m_RegionInfoCache.Cache(scopeID, rinfo);
244 return rinfo; 232 return rinfo;
245 } 233 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
index c33f7f5..044e0e5 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
@@ -64,7 +64,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
64 config.Configs["GridService"].Set("Region_Test_Region_3", "FallbackRegion"); 64 config.Configs["GridService"].Set("Region_Test_Region_3", "FallbackRegion");
65 config.Configs["GridService"].Set("Region_Other_Region_4", "FallbackRegion"); 65 config.Configs["GridService"].Set("Region_Other_Region_4", "FallbackRegion");
66 66
67 m_LocalConnector = new LocalGridServicesConnector(config); 67 m_LocalConnector = new LocalGridServicesConnector(config, null);
68 } 68 }
69 69
70 /// <summary> 70 /// <summary>