aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorUbitUmarov2016-07-31 23:19:51 +0100
committerUbitUmarov2016-07-31 23:19:51 +0100
commita9befe1c62a621c7e9b88a95a2e9e9df08df1a07 (patch)
treeaa88ad0018c1e9d69212ed9dce5b448d3bfb1f50
parentMerge branch 'master' into httptests (diff)
parent on 0.8 grids compatibility code just do a BIG range request. It whould be do... (diff)
downloadopensim-SC-a9befe1c62a621c7e9b88a95a2e9e9df08df1a07.zip
opensim-SC-a9befe1c62a621c7e9b88a95a2e9e9df08df1a07.tar.gz
opensim-SC-a9befe1c62a621c7e9b88a95a2e9e9df08df1a07.tar.bz2
opensim-SC-a9befe1c62a621c7e9b88a95a2e9e9df08df1a07.tar.xz
Merge branch 'master' into httptests
-rw-r--r--OpenSim/Framework/Util.cs42
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs163
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs28
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs14
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs622
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs14
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs12
7 files changed, 474 insertions, 421 deletions
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 1b3a4c3..5250d30 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -368,47 +368,49 @@ namespace OpenSim.Framework
368 return Utils.UIntsToLong(X, Y); 368 return Utils.UIntsToLong(X, Y);
369 } 369 }
370 370
371 // Regions are identified with a 'handle' made up of its region coordinates packed into a ulong. 371 // Regions are identified with a 'handle' made up of its world coordinates packed into a ulong.
372 // Several places rely on the ability to extract a region's location from its handle. 372 // Region handles are based on the coordinate of the region corner with lower X and Y
373 // Note the location is in 'world coordinates' (see below). 373 // var regions need more work than this to get that right corner from a generic world position
374 // Region handles are based on the lowest coordinate of the region so trim the passed x,y to be the regions 0,0. 374 // this corner must be on a grid point
375 public static ulong RegionWorldLocToHandle(uint X, uint Y) 375 public static ulong RegionWorldLocToHandle(uint X, uint Y)
376 { 376 {
377 return Utils.UIntsToLong(X, Y); 377 ulong handle = X & 0xffffff00; // make sure it matchs grid coord points.
378 handle <<= 32; // to higher half
379 handle |= (Y & 0xffffff00);
380 return handle;
378 } 381 }
379 382
380 public static ulong RegionLocToHandle(uint X, uint Y) 383 public static ulong RegionGridLocToHandle(uint X, uint Y)
381 { 384 {
382 return Utils.UIntsToLong(Util.RegionToWorldLoc(X), Util.RegionToWorldLoc(Y)); 385 ulong handle = X << 40; // shift to higher half and mult by 256)
386 handle |= (Y << 8); // mult by 256)
387 return handle;
383 } 388 }
384 389
385 public static void RegionHandleToWorldLoc(ulong handle, out uint X, out uint Y) 390 public static void RegionHandleToWorldLoc(ulong handle, out uint X, out uint Y)
386 { 391 {
387 X = (uint)(handle >> 32); 392 X = (uint)(handle >> 32);
388 Y = (uint)(handle & (ulong)uint.MaxValue); 393 Y = (uint)(handle & 0xfffffffful);
389 } 394 }
390 395
391 public static void RegionHandleToRegionLoc(ulong handle, out uint X, out uint Y) 396 public static void RegionHandleToRegionLoc(ulong handle, out uint X, out uint Y)
392 { 397 {
393 uint worldX, worldY; 398 X = (uint)(handle >> 40) & 0x00ffffffu; // bring from higher half, divide by 256 and clean
394 RegionHandleToWorldLoc(handle, out worldX, out worldY); 399 Y = (uint)(handle >> 8) & 0x00ffffffu; // divide by 256 and clean
395 X = WorldToRegionLoc(worldX); 400 // if you trust the uint cast then the clean can be removed.
396 Y = WorldToRegionLoc(worldY);
397 } 401 }
398 402
399 // A region location can be 'world coordinates' (meters from zero) or 'region coordinates' 403 // A region location can be 'world coordinates' (meters) or 'region grid coordinates'
400 // (number of regions from zero). This measurement of regions relies on the legacy 256 region size. 404 // grid coordinates have a fixed step of 256m as defined by viewers
401 // These routines exist to make what is being converted explicit so the next person knows what was meant.
402 // Convert a region's 'world coordinate' to its 'region coordinate'.
403 public static uint WorldToRegionLoc(uint worldCoord) 405 public static uint WorldToRegionLoc(uint worldCoord)
404 { 406 {
405 return worldCoord / Constants.RegionSize; 407 return worldCoord >> 8;
406 } 408 }
407 409
408 // Convert a region's 'region coordinate' to its 'world coordinate'. 410 // Convert a region's 'region grid coordinate' to its 'world coordinate'.
409 public static uint RegionToWorldLoc(uint regionCoord) 411 public static uint RegionToWorldLoc(uint regionCoord)
410 { 412 {
411 return regionCoord * Constants.RegionSize; 413 return regionCoord << 8;
412 } 414 }
413 415
414 public static T Clamp<T>(T x, T min, T max) 416 public static T Clamp<T>(T x, T min, T max)
@@ -1303,7 +1305,7 @@ namespace OpenSim.Framework
1303 } 1305 }
1304 catch (Exception e) 1306 catch (Exception e)
1305 { 1307 {
1306 m_log.WarnFormat("[UTILS]: Exception copying configuration file {0} to {1}: {2}", exampleConfigFile, configFile, e.Message); 1308 m_log.WarnFormat("[UTILS]: Exception copying configuration file {0} to {1}: {2}", configFile, exampleConfigFile, e.Message);
1307 return false; 1309 return false;
1308 } 1310 }
1309 } 1311 }
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index efc714f..980d3cc 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -1537,8 +1537,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1537 1537
1538 public ScenePresence CrossAsync(ScenePresence agent, bool isFlying) 1538 public ScenePresence CrossAsync(ScenePresence agent, bool isFlying)
1539 { 1539 {
1540 uint x;
1541 uint y;
1542 Vector3 newpos; 1540 Vector3 newpos;
1543 EntityTransferContext ctx = new EntityTransferContext(); 1541 EntityTransferContext ctx = new EntityTransferContext();
1544 string failureReason; 1542 string failureReason;
@@ -1588,7 +1586,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1588 1586
1589 agent.Scene.RequestTeleportLocation( 1587 agent.Scene.RequestTeleportLocation(
1590 agent.ControllingClient, 1588 agent.ControllingClient,
1591 Util.RegionLocToHandle(regionX, regionY), 1589 Util.RegionGridLocToHandle(regionX, regionY),
1592 position, 1590 position,
1593 agent.Lookat, 1591 agent.Lookat,
1594 (uint)Constants.TeleportFlags.ViaLocation); 1592 (uint)Constants.TeleportFlags.ViaLocation);
@@ -1814,7 +1812,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1814 // In any case 1812 // In any case
1815 agent.IsInTransit = false; 1813 agent.IsInTransit = false;
1816 1814
1817 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); 1815// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
1818 } 1816 }
1819 1817
1820 #endregion 1818 #endregion
@@ -2115,79 +2113,62 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2115 // contains that point. A conservitive estimate. 2113 // contains that point. A conservitive estimate.
2116 private class NotFoundLocationCache 2114 private class NotFoundLocationCache
2117 { 2115 {
2118 private struct NotFoundLocation 2116 private Dictionary<ulong, DateTime> m_notFoundLocations = new Dictionary<ulong, DateTime>();
2119 {
2120 public double minX, maxX, minY, maxY;
2121 public DateTime expireTime;
2122 }
2123 private List<NotFoundLocation> m_notFoundLocations = new List<NotFoundLocation>();
2124 public NotFoundLocationCache() 2117 public NotFoundLocationCache()
2125 { 2118 {
2126 } 2119 }
2127 // Add an area to the list of 'not found' places. The area is the snapped region 2120 // just use normal regions handlers and sizes
2128 // area around the added point.
2129 public void Add(double pX, double pY) 2121 public void Add(double pX, double pY)
2130 { 2122 {
2123 ulong psh = (ulong)pX & 0xffffff00ul;
2124 psh <<= 32;
2125 psh |= (ulong)pY & 0xffffff00ul;
2126
2131 lock (m_notFoundLocations) 2127 lock (m_notFoundLocations)
2132 { 2128 m_notFoundLocations[psh] = DateTime.Now + TimeSpan.FromSeconds(30);;
2133 if (!LockedContains(pX, pY))
2134 {
2135 NotFoundLocation nfl = new NotFoundLocation();
2136 // A not found location is not found for at least a whole region sized area
2137 nfl.minX = pX - (pX % (double)Constants.RegionSize);
2138 nfl.minY = pY - (pY % (double)Constants.RegionSize);
2139 nfl.maxX = nfl.minX + (double)Constants.RegionSize;
2140 nfl.maxY = nfl.minY + (double)Constants.RegionSize;
2141 nfl.expireTime = DateTime.Now + TimeSpan.FromSeconds(30);
2142 m_notFoundLocations.Add(nfl);
2143 }
2144 }
2145
2146 } 2129 }
2147 // Test to see of this point is in any of the 'not found' areas. 2130 // Test to see of this point is in any of the 'not found' areas.
2148 // Return 'true' if the point is found inside the 'not found' areas. 2131 // Return 'true' if the point is found inside the 'not found' areas.
2149 public bool Contains(double pX, double pY) 2132 public bool Contains(double pX, double pY)
2150 { 2133 {
2151 bool ret = false; 2134 ulong psh = (ulong)pX & 0xffffff00ul;
2135 psh <<= 32;
2136 psh |= (ulong)pY & 0xffffff00ul;
2137
2152 lock (m_notFoundLocations) 2138 lock (m_notFoundLocations)
2153 ret = LockedContains(pX, pY);
2154 return ret;
2155 }
2156 private bool LockedContains(double pX, double pY)
2157 {
2158 bool ret = false;
2159 this.DoExpiration();
2160 foreach (NotFoundLocation nfl in m_notFoundLocations)
2161 { 2139 {
2162 if (pX >= nfl.minX && pX < nfl.maxX && pY >= nfl.minY && pY < nfl.maxY) 2140 if(m_notFoundLocations.ContainsKey(psh))
2163 { 2141 {
2164 ret = true; 2142 if(m_notFoundLocations[psh] > DateTime.UtcNow)
2165 break; 2143 return true;
2144 m_notFoundLocations.Remove(psh);
2166 } 2145 }
2146 return false;
2167 } 2147 }
2168 return ret;
2169 } 2148 }
2149
2170 private void DoExpiration() 2150 private void DoExpiration()
2171 { 2151 {
2172 List<NotFoundLocation> m_toRemove = null; 2152 List<ulong> m_toRemove = new List<ulong>();;
2173 DateTime now = DateTime.Now; 2153 DateTime now = DateTime.UtcNow;
2174 foreach (NotFoundLocation nfl in m_notFoundLocations) 2154 lock (m_notFoundLocations)
2175 { 2155 {
2176 if (nfl.expireTime < now) 2156 foreach (KeyValuePair<ulong, DateTime> kvp in m_notFoundLocations)
2177 { 2157 {
2178 if (m_toRemove == null) 2158 if (kvp.Value < now)
2179 m_toRemove = new List<NotFoundLocation>(); 2159 m_toRemove.Add(kvp.Key);
2180 m_toRemove.Add(nfl); 2160 }
2161
2162 if (m_toRemove.Count > 0)
2163 {
2164 foreach (ulong u in m_toRemove)
2165 m_notFoundLocations.Remove(u);
2166 m_toRemove.Clear();
2181 } 2167 }
2182 }
2183 if (m_toRemove != null)
2184 {
2185 foreach (NotFoundLocation nfl in m_toRemove)
2186 m_notFoundLocations.Remove(nfl);
2187 m_toRemove.Clear();
2188 } 2168 }
2189 } 2169 }
2190 } 2170 }
2171
2191 #endregion // NotFoundLocationCache class 2172 #endregion // NotFoundLocationCache class
2192 private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache(); 2173 private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache();
2193 2174
@@ -2202,10 +2183,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2202 2183
2203 // Given a world position, get the GridRegion info for 2184 // Given a world position, get the GridRegion info for
2204 // the region containing that point. 2185 // the region containing that point.
2205 // Someday this should be a method on GridService.
2206 // 'pSizeHint' is the size of the source region but since the destination point can be anywhere
2207 // the size of the target region is unknown thus the search area might have to be very large.
2208 // Return 'null' if no such region exists.
2209 protected GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, 2186 protected GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID,
2210 double px, double py, uint pSizeHint) 2187 double px, double py, uint pSizeHint)
2211 { 2188 {
@@ -2213,11 +2190,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2213 GridRegion ret = null; 2190 GridRegion ret = null;
2214 const double fudge = 2.0; 2191 const double fudge = 2.0;
2215 2192
2216 // One problem with this routine is negative results. That is, this can be called lots of times
2217 // for regions that don't exist. m_notFoundLocationCache remembers 'not found' results so they
2218 // will be quick 'not found's next time.
2219 // NotFoundLocationCache is an expiring cache so it will eventually forget about 'not found' and
2220 // thus re-ask the GridService about the location.
2221 if (m_notFoundLocationCache.Contains(px, py)) 2193 if (m_notFoundLocationCache.Contains(px, py))
2222 { 2194 {
2223// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found via cache. loc=<{1},{2}>", LogHeader, px, py); 2195// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found via cache. loc=<{1},{2}>", LogHeader, px, py);
@@ -2226,60 +2198,45 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2226 2198
2227 // As an optimization, since most regions will be legacy sized regions (256x256), first try to get 2199 // As an optimization, since most regions will be legacy sized regions (256x256), first try to get
2228 // the region at the appropriate legacy region location. 2200 // the region at the appropriate legacy region location.
2229 uint possibleX = (uint)Math.Floor(px); 2201 // this is all that is needed on 0.9 grids
2230 possibleX -= possibleX % Constants.RegionSize; 2202 uint possibleX = (uint)px & 0xffffff00u;
2231 uint possibleY = (uint)Math.Floor(py); 2203 uint possibleY = (uint)py & 0xffffff00u;
2232 possibleY -= possibleY % Constants.RegionSize;
2233 ret = pGridService.GetRegionByPosition(pScopeID, (int)possibleX, (int)possibleY); 2204 ret = pGridService.GetRegionByPosition(pScopeID, (int)possibleX, (int)possibleY);
2234 if (ret != null) 2205 if (ret != null)
2235 { 2206 {
2236 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Found region using legacy size. rloc=<{1},{2}>. Rname={3}", 2207// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Found region using legacy size. rloc=<{1},{2}>. Rname={3}",
2237 LogHeader, possibleX, possibleY, ret.RegionName); 2208// LogHeader, possibleX, possibleY, ret.RegionName);
2209 return ret;
2238 } 2210 }
2239 2211
2240 if (ret == null) 2212 // for 0.8 regions just make a BIG area request. old code whould do it plus 4 more smaller on region open edges
2213 // this is what 0.9 grids now do internally
2214 List<GridRegion> possibleRegions = pGridService.GetRegionRange(pScopeID,
2215 (int)(px - Constants.MaximumRegionSize), (int)(px + 1), // +1 bc left mb not part of range
2216 (int)(py - Constants.MaximumRegionSize), (int)(py + 1));
2217// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegions cnt={1}, range={2}",
2218// LogHeader, possibleRegions.Count, range);
2219 if (possibleRegions != null && possibleRegions.Count > 0)
2241 { 2220 {
2242 // If the simple lookup failed, search the larger area for a region that contains this point 2221 // If we found some regions, check to see if the point is within
2243 double range = (double)pSizeHint + fudge; 2222 foreach (GridRegion gr in possibleRegions)
2244 while (ret == null && range <= (Constants.MaximumRegionSize + Constants.RegionSize))
2245 { 2223 {
2246 // Get from the grid service a list of regions that might contain this point. 2224// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegion nm={1}, regionLoc=<{2},{3}>, regionSize=<{4},{5}>",
2247 // The region origin will be in the zero direction so only subtract the range. 2225// LogHeader, gr.RegionName, gr.RegionLocX, gr.RegionLocY, gr.RegionSizeX, gr.RegionSizeY);
2248 List<GridRegion> possibleRegions = pGridService.GetRegionRange(pScopeID, 2226 if (px >= (double)gr.RegionLocX && px < (double)(gr.RegionLocX + gr.RegionSizeX)
2249 (int)(px - range), (int)(px),
2250 (int)(py - range), (int)(py));
2251 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegions cnt={1}, range={2}",
2252 LogHeader, possibleRegions.Count, range);
2253 if (possibleRegions != null && possibleRegions.Count > 0)
2254 {
2255 // If we found some regions, check to see if the point is within
2256 foreach (GridRegion gr in possibleRegions)
2257 {
2258 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: possibleRegion nm={1}, regionLoc=<{2},{3}>, regionSize=<{4},{5}>",
2259 LogHeader, gr.RegionName, gr.RegionLocX, gr.RegionLocY, gr.RegionSizeX, gr.RegionSizeY);
2260 if (px >= (double)gr.RegionLocX && px < (double)(gr.RegionLocX + gr.RegionSizeX)
2261 && py >= (double)gr.RegionLocY && py < (double)(gr.RegionLocY + gr.RegionSizeY)) 2227 && py >= (double)gr.RegionLocY && py < (double)(gr.RegionLocY + gr.RegionSizeY))
2262 { 2228 {
2263 // Found a region that contains the point 2229 // Found a region that contains the point
2264 ret = gr; 2230 return gr;
2265 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: found. RegionName={1}", LogHeader, ret.RegionName); 2231// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: found. RegionName={1}", LogHeader, ret.RegionName);
2266 break;
2267 }
2268 }
2269 } 2232 }
2270 // Larger search area for next time around if not found
2271 range *= 2;
2272 } 2233 }
2273 } 2234 }
2274 2235
2275 if (ret == null) 2236 // remember this location was not found so we can quickly not find it next time
2276 { 2237 m_notFoundLocationCache.Add(px, py);
2277 // remember this location was not found so we can quickly not find it next time 2238// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found. Remembering loc=<{1},{2}>", LogHeader, px, py);
2278 m_notFoundLocationCache.Add(px, py); 2239 return null;
2279 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found. Remembering loc=<{1},{2}>", LogHeader, px, py);
2280 }
2281
2282 return ret;
2283 } 2240 }
2284 2241
2285 private void InformClientOfNeighbourCompleted(IAsyncResult iar) 2242 private void InformClientOfNeighbourCompleted(IAsyncResult iar)
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
index e3c6c0d..acfdaef 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
@@ -101,7 +101,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
101 /// <returns>true if the agent was not already in transit, false if it was</returns> 101 /// <returns>true if the agent was not already in transit, false if it was</returns>
102 internal bool SetInTransit(UUID id) 102 internal bool SetInTransit(UUID id)
103 { 103 {
104 m_log.DebugFormat("{0} SetInTransit. agent={1}, newState=Preparing", LogHeader, id); 104// m_log.DebugFormat("{0} SetInTransit. agent={1}, newState=Preparing", LogHeader, id);
105 lock (m_agentsInTransit) 105 lock (m_agentsInTransit)
106 { 106 {
107 if (!m_agentsInTransit.ContainsKey(id)) 107 if (!m_agentsInTransit.ContainsKey(id))
@@ -123,7 +123,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
123 /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception> 123 /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception>
124 internal bool UpdateInTransit(UUID id, AgentTransferState newState) 124 internal bool UpdateInTransit(UUID id, AgentTransferState newState)
125 { 125 {
126 m_log.DebugFormat("{0} UpdateInTransit. agent={1}, newState={2}", LogHeader, id, newState); 126 // m_log.DebugFormat("{0} UpdateInTransit. agent={1}, newState={2}", LogHeader, id, newState);
127 127
128 bool transitionOkay = false; 128 bool transitionOkay = false;
129 129
@@ -247,32 +247,32 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
247 { 247 {
248 AgentTransferState state = m_agentsInTransit[id]; 248 AgentTransferState state = m_agentsInTransit[id];
249 249
250 if (state == AgentTransferState.Transferring || state == AgentTransferState.ReceivedAtDestination) 250// if (state == AgentTransferState.Transferring || state == AgentTransferState.ReceivedAtDestination)
251 { 251// {
252 // FIXME: For now, we allow exit from any state since a thrown exception in teleport is now guranteed 252 // FIXME: For now, we allow exit from any state since a thrown exception in teleport is now guranteed
253 // to be handled properly - ResetFromTransit() could be invoked at any step along the process 253 // to be handled properly - ResetFromTransit() could be invoked at any step along the process
254 m_log.WarnFormat( 254// m_log.WarnFormat(
255 "[ENTITY TRANSFER STATE MACHINE]: Agent with ID {0} should not exit directly from state {1}, should go to {2} state first in {3}", 255// "[ENTITY TRANSFER STATE MACHINE]: Agent with ID {0} should not exit directly from state {1}, should go to {2} state first in {3}",
256 id, state, AgentTransferState.CleaningUp, m_mod.Scene.RegionInfo.RegionName); 256// id, state, AgentTransferState.CleaningUp, m_mod.Scene.RegionInfo.RegionName);
257 257
258// throw new Exception( 258// throw new Exception(
259// "Agent with ID {0} cannot exit directly from state {1}, it must go to {2} state first", 259// "Agent with ID {0} cannot exit directly from state {1}, it must go to {2} state first",
260// state, AgentTransferState.CleaningUp); 260// state, AgentTransferState.CleaningUp);
261 } 261// }
262 262
263 m_agentsInTransit.Remove(id); 263 m_agentsInTransit.Remove(id);
264 264
265 m_log.DebugFormat( 265// m_log.DebugFormat(
266 "[ENTITY TRANSFER STATE MACHINE]: Agent {0} cleared from transit in {1}", 266// "[ENTITY TRANSFER STATE MACHINE]: Agent {0} cleared from transit in {1}",
267 id, m_mod.Scene.RegionInfo.RegionName); 267// id, m_mod.Scene.RegionInfo.RegionName);
268 268
269 return true; 269 return true;
270 } 270 }
271 } 271 }
272 272
273 m_log.WarnFormat( 273// m_log.WarnFormat(
274 "[ENTITY TRANSFER STATE MACHINE]: Agent {0} requested to clear from transit in {1} but was already cleared", 274// "[ENTITY TRANSFER STATE MACHINE]: Agent {0} requested to clear from transit in {1} but was already cleared",
275 id, m_mod.Scene.RegionInfo.RegionName); 275// id, m_mod.Scene.RegionInfo.RegionName);
276 276
277 return false; 277 return false;
278 } 278 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
index d38ac9b..7d8ae57 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
@@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
166 if (!m_Enabled) 166 if (!m_Enabled)
167 return; 167 return;
168 168
169 m_RegionInfoCache.Remove(scene.RegionInfo.ScopeID, scene.RegionInfo.RegionID); 169 m_RegionInfoCache.Remove(scene.RegionInfo.ScopeID, scene.RegionInfo.RegionHandle);
170 scene.EventManager.OnRegionUp -= OnRegionUp; 170 scene.EventManager.OnRegionUp -= OnRegionUp;
171 } 171 }
172 172
@@ -220,16 +220,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
220 // be the base coordinate of the region. 220 // be the base coordinate of the region.
221 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) 221 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
222 { 222 {
223
223 // try in cache by handler first 224 // try in cache by handler first
224 ulong regionHandle = Util.RegionWorldLocToHandle((uint)x, (uint)y); 225// ulong regionHandle = Util.RegionWorldLocToHandle((uint)x, (uint)y);
225 226
226 bool inCache = false; 227 bool inCache = false;
227 GridRegion rinfo = m_RegionInfoCache.Get(scopeID, regionHandle, out inCache); 228// GridRegion rinfo = m_RegionInfoCache.Get(scopeID, regionHandle, out inCache);
228 if (inCache) 229// if (inCache)
229 return rinfo; 230// return rinfo;
230 231
231 // try in cache by slower position next 232 GridRegion rinfo = m_RegionInfoCache.Get(scopeID, (uint)x, (uint)y, out inCache);
232 rinfo = m_RegionInfoCache.Get(scopeID, x, y, out inCache);
233 if (inCache) 233 if (inCache)
234 return rinfo; 234 return rinfo;
235 235
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs
index 8f3dfc1..6db9515 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs
@@ -44,11 +44,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
44// LogManager.GetLogger( 44// LogManager.GetLogger(
45// MethodBase.GetCurrentMethod().DeclaringType); 45// MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 private RegionsExpiringCache m_Cache; 47 private static RegionsExpiringCache m_Cache;
48 private int numberInstances;
48 49
49 public RegionInfoCache() 50 public RegionInfoCache()
50 { 51 {
51 m_Cache = new RegionsExpiringCache(); 52 if(m_Cache == null)
53 m_Cache = new RegionsExpiringCache();
54 numberInstances++;
52 } 55 }
53 56
54 public void Cache(GridRegion rinfo) 57 public void Cache(GridRegion rinfo)
@@ -78,8 +81,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
78 if (rinfo == null) 81 if (rinfo == null)
79 return; 82 return;
80 83
81// m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS); 84 m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS);
82 m_Cache.Add(scopeID, rinfo, CACHE_EXPIRATION_SECONDS); // don't override local regions
83 } 85 }
84 86
85 public void Cache(UUID scopeID, GridRegion rinfo, float expireSeconds) 87 public void Cache(UUID scopeID, GridRegion rinfo, float expireSeconds)
@@ -90,9 +92,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
90 m_Cache.AddOrUpdate(scopeID, rinfo, expireSeconds); 92 m_Cache.AddOrUpdate(scopeID, rinfo, expireSeconds);
91 } 93 }
92 94
93 public void Remove(UUID scopeID, UUID regionID) 95 public void Remove(UUID scopeID, GridRegion rinfo)
96 {
97 m_Cache.Remove(scopeID, rinfo);
98 }
99
100 public void Remove(UUID scopeID, ulong regionHandle)
94 { 101 {
95 m_Cache.Remove(scopeID, regionID); 102 m_Cache.Remove(scopeID, regionHandle);
96 } 103 }
97 104
98 public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache) 105 public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache)
@@ -137,7 +144,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
137 return null; 144 return null;
138 } 145 }
139 146
140 public GridRegion Get(UUID scopeID, int x, int y, out bool inCache) 147 public GridRegion Get(UUID scopeID, uint x, uint y, out bool inCache)
141 { 148 {
142 inCache = false; 149 inCache = false;
143 150
@@ -152,109 +159,285 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
152 } 159 }
153 } 160 }
154 161
155 162 public class RegionInfoForScope
156 // following code partialy adapted from lib OpenMetaverse
157 public class RegionKey
158 { 163 {
159 public UUID ScopeID; 164 public const ulong HANDLEMASH = 0xffffff00ffffff00ul;
160 public UUID RegionID; 165 public const ulong HANDLECOORDMASH = 0xffffff00ul;
166
167 private Dictionary<ulong, GridRegion> storage;
168 private Dictionary<ulong, DateTime> expires;
169 private Dictionary<string, ulong> byname;
170 private Dictionary<UUID, ulong> byuuid;
161 171
162 public RegionKey(UUID scopeID, UUID id) 172 public RegionInfoForScope()
163 { 173 {
164 ScopeID = scopeID; 174 storage = new Dictionary<ulong, GridRegion>();
165 RegionID = id; 175 expires = new Dictionary<ulong, DateTime>();
176 byname = new Dictionary<string, ulong>();
177 byuuid = new Dictionary<UUID, ulong>();
166 } 178 }
167 179
168 public override int GetHashCode() 180 public RegionInfoForScope(GridRegion region, DateTime expire)
169 { 181 {
170 int hash = ScopeID.GetHashCode(); 182 storage = new Dictionary<ulong, GridRegion>();
171 hash += hash * 23 + RegionID.GetHashCode(); 183 expires = new Dictionary<ulong, DateTime>();
172 return hash; 184 byname = new Dictionary<string, ulong>();
185 byuuid = new Dictionary<UUID, ulong>();
186
187 ulong handle = region.RegionHandle & HANDLEMASH;
188 storage[handle] = region;
189 expires[handle] = expire;
190 byname[region.RegionName] = handle;
191 byuuid[region.RegionID] = handle;
173 } 192 }
174 193
175 public override bool Equals(Object b) 194 public void Add(GridRegion region, DateTime expire)
176 { 195 {
177 if(b == null) 196 ulong handle = region.RegionHandle & HANDLEMASH;
178 return false; 197
179 RegionKey kb = b as RegionKey; 198 if(storage != null && storage.ContainsKey(handle))
180 return (ScopeID == kb.ScopeID && RegionID == kb.RegionID); 199 return;
200
201 if(storage == null)
202 storage = new Dictionary<ulong, GridRegion>();
203 if(expires == null)
204 expires = new Dictionary<ulong, DateTime>();
205 if(byname == null)
206 byname = new Dictionary<string, ulong>();
207 if(byuuid == null)
208 byuuid = new Dictionary<UUID, ulong>();
209
210 storage[handle] = region;
211 expires[handle] = expire;
212 byname[region.RegionName] = handle;
213 byuuid[region.RegionID] = handle;
181 } 214 }
182 }
183 215
184 class RegionKeyEqual : EqualityComparer<RegionKey> 216 public void AddUpdate(GridRegion region, DateTime expire)
185 {
186 public override int GetHashCode(RegionKey rk)
187 { 217 {
188 return rk.GetHashCode(); 218 if(storage == null)
219 storage = new Dictionary<ulong, GridRegion>();
220 if(expires == null)
221 expires = new Dictionary<ulong, DateTime>();
222 if(byname == null)
223 byname = new Dictionary<string, ulong>();
224 if(byuuid == null)
225 byuuid = new Dictionary<UUID, ulong>();
226
227 ulong handle = region.RegionHandle & HANDLEMASH;
228
229 storage[handle] = region;
230 if(expires.ContainsKey(handle))
231 {
232 if(expires[handle] < expire)
233 expires[handle] = expire;
234 }
235 else
236 expires[handle] = expire;
237 byname[region.RegionName] = handle;
238 byuuid[region.RegionID] = handle;
189 } 239 }
190 240
191 public override bool Equals(RegionKey a, RegionKey b) 241 public void Remove(GridRegion region)
192 { 242 {
193 return (a.ScopeID == b.ScopeID && a.RegionID == b.RegionID); 243 if(region == null)
244 return;
245
246 if(byname != null)
247 byname.Remove(region.RegionName);
248 if(byuuid != null)
249 byuuid.Remove(region.RegionID);
250
251 ulong handle = region.RegionHandle & HANDLEMASH;
252 if(storage != null)
253 storage.Remove(handle);
254 if(expires != null)
255 {
256 expires.Remove(handle);
257 if(expires.Count == 0)
258 Clear();
259 }
194 } 260 }
195 }
196 261
197 public class RegionInfoByScope 262 public void Remove(ulong handle)
198 { 263 {
199 private Dictionary<string, RegionKey> byname; 264 handle &= HANDLEMASH;
200 private Dictionary<ulong, RegionKey> byhandle; 265
266 if(storage != null)
267 {
268 if(storage.ContainsKey(handle))
269 {
270 GridRegion r = storage[handle];
271 if(byname != null)
272 byname.Remove(r.RegionName);
273 if(byuuid != null)
274 byuuid.Remove(r.RegionID);
275 }
276 storage.Remove(handle);
277 }
278 if(expires != null)
279 {
280 expires.Remove(handle);
281 if(expires.Count == 0)
282 Clear();
283 }
284 }
201 285
202 public RegionInfoByScope() 286 public void Clear()
203 { 287 {
204 byname = new Dictionary<string, RegionKey>(); 288 if(expires != null)
205 byhandle = new Dictionary<ulong, RegionKey>(); 289 expires.Clear();
290 if(storage != null)
291 storage.Clear();
292 if(byname != null)
293 byname.Clear();
294 if(byuuid != null)
295 byuuid.Clear();
296 byname = null;
297 byuuid = null;
298 storage = null;
299 expires = null;
206 } 300 }
207 301
208 public RegionInfoByScope(GridRegion region, RegionKey key) 302 public bool Contains(GridRegion region)
209 { 303 {
210 byname = new Dictionary<string, RegionKey>(); 304 if(storage == null)
211 byhandle = new Dictionary<ulong, RegionKey>(); 305 return false;
306 if(region == null)
307 return false;
212 308
213 byname[region.RegionName] = key; 309 ulong handle = region.RegionHandle & HANDLEMASH;
214 byhandle[region.RegionHandle] = key; 310 return storage.ContainsKey(handle);
215 } 311 }
216 312
217 public void AddRegion(GridRegion region, RegionKey key) 313 public bool Contains(ulong handle)
218 { 314 {
219 if(byname == null) 315 if(storage == null)
220 byname = new Dictionary<string, RegionKey>(); 316 return false;
221 if(byhandle == null)
222 byhandle = new Dictionary<ulong, RegionKey>();
223 317
224 byname[region.RegionName] = key; 318 handle &= HANDLEMASH;
225 byhandle[region.RegionHandle] = key; 319 return storage.ContainsKey(handle);
226 } 320 }
227 321
228 public void RemoveRegion(GridRegion region) 322 public GridRegion get(ulong handle)
229 { 323 {
230 if(byname != null) 324 if(storage == null)
231 byname.Remove(region.RegionName); 325 return null;
232 if(byhandle != null) 326
233 byhandle.Remove(region.RegionHandle); 327 handle &= HANDLEMASH;
328 if(storage.ContainsKey(handle))
329 return storage[handle];
330
331 return null;
234 } 332 }
235 333
236 public void Clear() 334 public GridRegion get(string name)
237 { 335 {
238 if(byname != null) 336 if(byname == null || !byname.ContainsKey(name))
239 byname.Clear(); 337 return null;
240 if(byhandle != null) 338
241 byhandle.Clear(); 339 ulong handle = byname[name];
242 byname = null; 340 if(storage.ContainsKey(handle))
243 byhandle = null; 341 return storage[handle];
342 return null;
244 } 343 }
245 344
246 public RegionKey get(string name) 345 public GridRegion get(UUID id)
247 { 346 {
248 if(byname == null || !byname.ContainsKey(name)) 347 if(byuuid == null || !byuuid.ContainsKey(id))
249 return null; 348 return null;
250 return byname[name]; 349
350 ulong handle = byuuid[id];
351 if(storage.ContainsKey(handle))
352 return storage[handle];
353 return null;
251 } 354 }
252 355
253 public RegionKey get(ulong handle) 356 public GridRegion get(uint x, uint y)
254 { 357 {
255 if(byhandle == null || !byhandle.ContainsKey(handle)) 358 if(storage == null)
256 return null; 359 return null;
257 return byhandle[handle]; 360
361 // look for a handle first this should find normal size regions
362 ulong handle = (ulong)x & HANDLECOORDMASH;
363 handle <<= 32;
364 handle |= ((ulong)y & HANDLECOORDMASH);
365
366 if(storage.ContainsKey(handle))
367 return storage[handle];
368
369 // next do the harder work
370 foreach(KeyValuePair<ulong, GridRegion> kvp in storage)
371 {
372 GridRegion r = kvp.Value;
373 if(r == null) // ??
374 continue;
375
376 int test = r.RegionLocX;
377 if(x < test)
378 continue;
379 test += r.RegionSizeX;
380 if(x >= test)
381 continue;
382 test = r.RegionLocY;
383 if (y < test)
384 continue;
385 test += r.RegionSizeY;
386 if (y < test)
387 return r;
388 }
389 return null;
390 }
391
392 public int expire(DateTime now )
393 {
394 if(expires == null || expires.Count == 0)
395 return 0;
396
397 List<ulong> toexpire = new List<ulong>();
398 foreach(KeyValuePair<ulong, DateTime> kvp in expires)
399 {
400 if(kvp.Value < now)
401 toexpire.Add(kvp.Key);
402 }
403
404 if(toexpire.Count == 0)
405 return expires.Count;
406
407 if(toexpire.Count == expires.Count)
408 {
409 Clear();
410 return 0;
411 }
412
413 foreach(ulong h in toexpire)
414 {
415 if(storage != null)
416 {
417 if(storage.ContainsKey(h))
418 {
419 GridRegion r = storage[h];
420 if(byname != null)
421 byname.Remove(r.RegionName);
422 if(byuuid != null)
423 byuuid.Remove(r.RegionID);
424 }
425 storage.Remove(h);
426 }
427 if(expires != null)
428 expires.Remove(h);
429 }
430
431 if(expires.Count == 0)
432 {
433 byname = null;
434 byuuid = null;
435 storage = null;
436 expires = null;
437 return 0;
438 }
439
440 return expires.Count;
258 } 441 }
259 442
260 public int Count() 443 public int Count()
@@ -276,10 +459,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
276 /// <summary>For thread safety</summary> 459 /// <summary>For thread safety</summary>
277 object isPurging = new object(); 460 object isPurging = new object();
278 461
279 static RegionKeyEqual keyequal = new RegionKeyEqual(); 462 Dictionary<UUID, RegionInfoForScope> InfobyScope = new Dictionary<UUID, RegionInfoForScope>();
280 Dictionary<RegionKey, GridRegion> timedStorage = new Dictionary<RegionKey, GridRegion>(keyequal);
281 Dictionary<RegionKey, DateTime> timedExpires = new Dictionary<RegionKey, DateTime>();
282 Dictionary<UUID, RegionInfoByScope> InfobyScope = new Dictionary<UUID, RegionInfoByScope>();
283 private System.Timers.Timer timer = new System.Timers.Timer(TimeSpan.FromSeconds(CACHE_PURGE_HZ).TotalMilliseconds); 463 private System.Timers.Timer timer = new System.Timers.Timer(TimeSpan.FromSeconds(CACHE_PURGE_HZ).TotalMilliseconds);
284 464
285 public RegionsExpiringCache() 465 public RegionsExpiringCache()
@@ -288,297 +468,225 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
288 timer.Start(); 468 timer.Start();
289 } 469 }
290 470
291 public bool Add(UUID scope, GridRegion region, float expirationSeconds) 471 public bool AddOrUpdate(UUID scope, GridRegion region, float expirationSeconds)
292 { 472 {
473 if(region == null)
474 return false;
475
293 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) 476 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
294 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); 477 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
295 478
296 RegionKey key = new RegionKey(scope , region.RegionID);
297
298 try 479 try
299 { 480 {
300 if (timedStorage.ContainsKey(key))
301 return false;
302
303 DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds); 481 DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
304 timedStorage[key] = region;
305 timedExpires[key] = expire;
306 482
307 RegionInfoByScope ris = null; 483 RegionInfoForScope ris = null;
308 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null) 484 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
309 { 485 {
310 ris = new RegionInfoByScope(region, key); 486 ris = new RegionInfoForScope(region, expire);
311 InfobyScope[scope] = ris; 487 InfobyScope[scope] = ris;
312 } 488 }
313 else 489 else
314 ris.AddRegion(region, key); 490 ris.AddUpdate(region, expire);
315 491
316 return true; 492 return true;
317 } 493 }
318 finally { Monitor.Exit(syncRoot);} 494 finally { Monitor.Exit(syncRoot); }
319 } 495 }
320 496
321 public bool AddOrUpdate(UUID scope, GridRegion region, float expirationSeconds) 497 public void Clear()
322 { 498 {
323 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) 499 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
324 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); 500 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
325
326 try 501 try
327 { 502 {
328 RegionKey key = new RegionKey(scope, region.RegionID); 503 foreach(RegionInfoForScope ris in InfobyScope.Values)
329 DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds); 504 ris.Clear();
505 InfobyScope.Clear();
506 }
507 finally { Monitor.Exit(syncRoot); }
508 }
509
510 public bool Contains(UUID scope, GridRegion region)
511 {
512 if(region == null)
513 return false;
330 514
331 if (timedStorage.ContainsKey(key)) 515 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
332 { 516 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
333 timedStorage[key] = region;
334 if(expire > timedExpires[key])
335 timedExpires[key] = expire;
336 517
337 if(!InfobyScope.ContainsKey(scope)) 518 try
338 { 519 {
339 RegionInfoByScope ris = new RegionInfoByScope(region, key); 520 RegionInfoForScope ris = null;
340 InfobyScope[scope] = ris; 521 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
341 }
342 return false; 522 return false;
343 } 523
344 else 524 return ris.Contains(region);
345 {
346 timedStorage[key] = region;
347 timedExpires[key] = expire;
348 RegionInfoByScope ris = null;
349 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
350 {
351 ris = new RegionInfoByScope(region,key);
352 InfobyScope[scope] = ris;
353 }
354 else
355 ris.AddRegion(region,key);
356 return true;
357 }
358 } 525 }
359 finally { Monitor.Exit(syncRoot); } 526 finally { Monitor.Exit(syncRoot); }
360 } 527 }
361 528
362 public void Clear() 529 public bool Contains(UUID scope, ulong handle)
363 { 530 {
364 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) 531 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
365 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); 532 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
533
366 try 534 try
367 { 535 {
368 timedStorage.Clear(); 536 RegionInfoForScope ris = null;
369 timedExpires.Clear(); 537 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
370 InfobyScope.Clear(); 538 return false;
539
540 return ris.Contains(handle);
371 } 541 }
372 finally { Monitor.Exit(syncRoot); } 542 finally { Monitor.Exit(syncRoot); }
373 } 543 }
374
375 public bool Contains(UUID scope, GridRegion region)
376 {
377 RegionKey key = new RegionKey(scope, region.RegionID);
378 return Contains(key);
379 }
380 544
381 public bool Contains(RegionKey key) 545 public int Count()
382 { 546 {
383 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) 547 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
384 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); 548 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
549
385 try 550 try
386 { 551 {
387 return timedStorage.ContainsKey(key); 552 int count = 0;
553 foreach(RegionInfoForScope ris in InfobyScope.Values)
554 count += ris.Count();
555 return count;
388 } 556 }
389 finally { Monitor.Exit(syncRoot); } 557 finally { Monitor.Exit(syncRoot); }
390 } 558 }
391 559
392 public int Count 560 public bool Remove(UUID scope, ulong handle)
393 {
394 get
395 {
396 return timedStorage.Count;
397 }
398 }
399 public bool Remove(UUID scope, GridRegion region)
400 { 561 {
401 return Remove(scope, region.RegionID);
402 }
403 public bool Remove(UUID scope, UUID regionID)
404 {
405 RegionKey key = new RegionKey(scope, regionID);
406
407 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) 562 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
408 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); 563 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
409 try 564 try
410 { 565 {
411 if (timedStorage.ContainsKey(key)) 566 RegionInfoForScope ris = null;
412 { 567 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
413 RegionInfoByScope ris = null;
414 if(InfobyScope.TryGetValue(scope, out ris) && ris != null)
415 {
416 GridRegion r = timedStorage[key];
417 if(r != null)
418 ris.RemoveRegion(r);
419 if(ris.Count() == 0)
420 InfobyScope.Remove(scope);
421 }
422 timedStorage.Remove(key);
423 timedExpires.Remove(key);
424 return true;
425 }
426 else
427 return false; 568 return false;
569
570 ris.Remove(handle);
571 if(ris.Count() == 0)
572 InfobyScope.Remove(scope);
573 return true;
428 } 574 }
429 finally { Monitor.Exit(syncRoot); } 575 finally { Monitor.Exit(syncRoot); }
430 } 576 }
431 577
432 public bool TryGetValue(RegionKey key, out GridRegion value) 578 public bool Remove(UUID scope, GridRegion region)
433 { 579 {
580 if(region == null)
581 return false;
582
434 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) 583 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
435 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); 584 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
436 try 585 try
437 { 586 {
438 if (timedStorage.ContainsKey(key)) 587 RegionInfoForScope ris = null;
439 { 588 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
440 value = timedStorage[key]; 589 return false;
441 return true; 590
442 } 591 ris.Remove(region);
592 if(ris.Count() == 0)
593 InfobyScope.Remove(scope);
594 return true;
443 } 595 }
444 finally { Monitor.Exit(syncRoot); } 596 finally { Monitor.Exit(syncRoot); }
445
446 value = null;
447 return false;
448 } 597 }
449 598
450 public bool TryGetValue(UUID scope, UUID id, out GridRegion value) 599 public bool TryGetValue(UUID scope, ulong handle, out GridRegion value)
451 { 600 {
452 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) 601 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
453 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); 602 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
603
604 value = null;
454 try 605 try
455 { 606 {
456 RegionKey rk = new RegionKey(scope, id); 607 RegionInfoForScope ris = null;
457 if(timedStorage.ContainsKey(rk)) 608 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
458 { 609 return false;
459 value = timedStorage[rk]; 610 value = ris.get(handle);
460 return true;
461 }
462 } 611 }
463 finally { Monitor.Exit(syncRoot); } 612 finally { Monitor.Exit(syncRoot); }
464 613
465 value = null; 614 return value != null;
466 return false;
467 } 615 }
468 616
469 public bool TryGetValue(UUID scope, string name, out GridRegion value) 617 public bool TryGetValue(UUID scope, string name, out GridRegion value)
470 { 618 {
471 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) 619 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
472 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); 620 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
621
622 value = null;
473 try 623 try
474 { 624 {
475 value = null; 625 RegionInfoForScope ris = null;
476 RegionInfoByScope ris = null;
477 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null) 626 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
478 return false; 627 return false;
479 628 value = ris.get(name);
480 RegionKey key = ris.get(name);
481 if(key == null)
482 return false;
483
484 if(timedStorage.ContainsKey(key))
485 {
486 value = timedStorage[key];
487 return true;
488 }
489 } 629 }
490 finally { Monitor.Exit(syncRoot); } 630 finally { Monitor.Exit(syncRoot); }
491 631
492 return false; 632 return value != null;
493 } 633 }
494 634
495 public bool TryGetValue(UUID scope, ulong handle, out GridRegion value) 635 public bool TryGetValue(UUID scope, UUID id, out GridRegion value)
496 { 636 {
497 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) 637 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
498 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); 638 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
639
640 value = null;
499 try 641 try
500 { 642 {
501 value = null; 643 RegionInfoForScope ris = null;
502 RegionInfoByScope ris = null;
503 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null) 644 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
504 return false; 645 return false;
505 646 value = ris.get(id);
506 RegionKey key = ris.get(handle);
507 if(key == null)
508 return false;
509
510 if(timedStorage.ContainsKey(key))
511 {
512 value = timedStorage[key];
513 return true;
514 }
515 } 647 }
516 finally { Monitor.Exit(syncRoot); } 648 finally { Monitor.Exit(syncRoot); }
517 649
518 value = null; 650 return value != null;
519 return false;
520 } 651 }
521 652
522 // gets a region that contains world position (x,y) 653 // gets a region that contains world position (x,y)
523 // hopefull will not take ages 654 // hopefull will not take ages
524 public bool TryGetValue(UUID scope, int x, int y, out GridRegion value) 655 public bool TryGetValue(UUID scope, uint x, uint y, out GridRegion value)
525 { 656 {
526 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) 657 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
527 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); 658 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
659
660 value = null;
528 try 661 try
529 { 662 {
530 value = null; 663 RegionInfoForScope ris = null;
531 664 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
532 if(timedStorage.Count == 0)
533 return false; 665 return false;
534 666
535 foreach(KeyValuePair<RegionKey, GridRegion> kvp in timedStorage) 667 value = ris.get(x, y);
536 {
537 if(kvp.Key.ScopeID != scope)
538 continue;
539
540 GridRegion r = kvp.Value;
541 if(r == null) // ??
542 continue;
543 int test = r.RegionLocX;
544 if(x < test)
545 continue;
546 test += r.RegionSizeX;
547 if(x >= test)
548 continue;
549 test = r.RegionLocY;
550 if(y < test)
551 continue;
552 test += r.RegionSizeY;
553 if (y < test)
554 {
555 value = r;
556 return true;
557 }
558 }
559 } 668 }
560 finally { Monitor.Exit(syncRoot); } 669 finally { Monitor.Exit(syncRoot); }
561 670
562 value = null; 671 return value != null;
563 return false;
564 } 672 }
565 673
566 public bool Update(UUID scope, GridRegion region, double expirationSeconds) 674 public bool Update(UUID scope, GridRegion region, double expirationSeconds)
567 { 675 {
676 if(region == null)
677 return false;
678
568 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT)) 679 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
569 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms"); 680 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
570 681
571 RegionKey key = new RegionKey(scope, region.RegionID);
572 try 682 try
573 { 683 {
574 if (!timedStorage.ContainsKey(key)) 684 RegionInfoForScope ris = null;
685 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
575 return false; 686 return false;
576 687
577 DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds); 688 DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
578 timedStorage[key] = region; 689 ris.AddUpdate(region,expire);
579 if(expire > timedExpires[key])
580 timedExpires[key] = expire;
581
582 return true; 690 return true;
583 } 691 }
584 finally { Monitor.Exit(syncRoot); } 692 finally { Monitor.Exit(syncRoot); }
@@ -595,7 +703,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
595 if (!Monitor.TryEnter(isPurging)) 703 if (!Monitor.TryEnter(isPurging))
596 return; 704 return;
597 705
598 DateTime signalTime = DateTime.UtcNow; 706 DateTime now = DateTime.UtcNow;
599 707
600 try 708 try
601 { 709 {
@@ -604,32 +712,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
604 return; 712 return;
605 try 713 try
606 { 714 {
607 List<RegionKey> expiredkeys = new List<RegionKey>(); 715 List<UUID> expiredscopes = new List<UUID>();
608 716
609 foreach (KeyValuePair<RegionKey, DateTime> kvp in timedExpires) 717 foreach (KeyValuePair<UUID, RegionInfoForScope> kvp in InfobyScope)
610 { 718 {
611 if (kvp.Value < signalTime) 719 if (kvp.Value.expire(now) == 0)
612 expiredkeys.Add(kvp.Key); 720 expiredscopes.Add(kvp.Key);
613 } 721 }
614 722
615 if (expiredkeys.Count > 0) 723 if (expiredscopes.Count > 0)
616 { 724 {
617 RegionInfoByScope ris; 725 foreach (UUID sid in expiredscopes)
618 foreach (RegionKey key in expiredkeys) 726 InfobyScope.Remove(sid);
619 {
620 ris = null;
621 if(InfobyScope.TryGetValue(key.ScopeID, out ris) && ris != null)
622 {
623 GridRegion r = timedStorage[key];
624 if(r != null)
625 ris.RemoveRegion(r);
626
627 if(ris.Count() == 0)
628 InfobyScope.Remove(key.ScopeID);
629 }
630 timedStorage.Remove(key);
631 timedExpires.Remove(key);
632 }
633 } 727 }
634 } 728 }
635 finally { Monitor.Exit(syncRoot); } 729 finally { Monitor.Exit(syncRoot); }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
index 96ff4b3..e6e3abb 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
@@ -204,8 +204,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
204 GridRegion rinfo = m_LocalGridService.GetRegionByPosition(scopeID, x, y); 204 GridRegion rinfo = m_LocalGridService.GetRegionByPosition(scopeID, x, y);
205 if (rinfo != null) 205 if (rinfo != null)
206 { 206 {
207 m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Added region {0} to the cache from local. Pos=<{1},{2}>, RegionHandle={3}", 207// m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Found region {0} on local. Pos=<{1},{2}>, RegionHandle={3}",
208 rinfo.RegionName, rinfo.RegionCoordX, rinfo.RegionCoordY, rinfo.RegionHandle); 208// rinfo.RegionName, rinfo.RegionCoordX, rinfo.RegionCoordY, rinfo.RegionHandle);
209 return rinfo; 209 return rinfo;
210 } 210 }
211 211
@@ -213,16 +213,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
213 213
214 if (rinfo == null) 214 if (rinfo == null)
215 { 215 {
216 uint regionX = Util.WorldToRegionLoc((uint)x); 216// uint regionX = Util.WorldToRegionLoc((uint)x);
217 uint regionY = Util.WorldToRegionLoc((uint)y); 217// uint regionY = Util.WorldToRegionLoc((uint)y);
218 m_log.WarnFormat("[REMOTE GRID CONNECTOR]: Requested region {0}-{1} not found", regionX, regionY); 218// m_log.WarnFormat("[REMOTE GRID CONNECTOR]: Requested region {0}-{1} not found", regionX, regionY);
219 } 219 }
220 else 220 else
221 { 221 {
222 m_RegionInfoCache.Cache(scopeID, rinfo); 222 m_RegionInfoCache.Cache(scopeID, rinfo);
223 223
224 m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Added region {0} to the cache. Pos=<{1},{2}>, RegionHandle={3}", 224// m_log.DebugFormat("[REMOTE GRID CONNECTOR]: GetRegionByPosition. Added region {0} to the cache. Pos=<{1},{2}>, RegionHandle={3}",
225 rinfo.RegionName, rinfo.RegionCoordX, rinfo.RegionCoordY, rinfo.RegionHandle); 225// rinfo.RegionName, rinfo.RegionCoordX, rinfo.RegionCoordY, rinfo.RegionHandle);
226 } 226 }
227 return rinfo; 227 return rinfo;
228 } 228 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 319f14c..e525a2e 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -852,19 +852,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
852 } 852 }
853 } 853 }
854 854
855 public void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) 855 public void osTeleportAgent(string agent, int regionGridX, int regionGridY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat)
856 { 856 {
857 // High because there is no security check. High griefer potential 857 // High because there is no security check. High griefer potential
858 // 858 //
859 CheckThreatLevel(ThreatLevel.Severe, "osTeleportAgent"); 859 CheckThreatLevel(ThreatLevel.Severe, "osTeleportAgent");
860 860
861 TeleportAgent(agent, regionX, regionY, position, lookat, false); 861 TeleportAgent(agent, regionGridX, regionGridY, position, lookat, false);
862 } 862 }
863 863
864 private void TeleportAgent(string agent, int regionX, int regionY, 864 private void TeleportAgent(string agent, int regionGridX, int regionGridY,
865 LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions) 865 LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions)
866 { 866 {
867 ulong regionHandle = Util.RegionLocToHandle((uint)regionX, (uint)regionY); 867 ulong regionHandle = Util.RegionGridLocToHandle((uint)regionGridX, (uint)regionGridY);
868 868
869 m_host.AddScriptLPS(1); 869 m_host.AddScriptLPS(1);
870 UUID agentId = new UUID(); 870 UUID agentId = new UUID();
@@ -917,11 +917,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
917 osTeleportOwner(World.RegionInfo.RegionName, position, lookat); 917 osTeleportOwner(World.RegionInfo.RegionName, position, lookat);
918 } 918 }
919 919
920 public void osTeleportOwner(int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) 920 public void osTeleportOwner(int regionGridX, int regionGridY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat)
921 { 921 {
922 CheckThreatLevel(ThreatLevel.None, "osTeleportOwner"); 922 CheckThreatLevel(ThreatLevel.None, "osTeleportOwner");
923 923
924 TeleportAgent(m_host.OwnerID.ToString(), regionX, regionY, position, lookat, true); 924 TeleportAgent(m_host.OwnerID.ToString(), regionGridX, regionGridY, position, lookat, true);
925 } 925 }
926 926
927 ///<summary> 927 ///<summary>