a few more changes to worldMap. Use ExpireCaches, cache remote mapItems requests, etc
parent
87ad573ec2
commit
ba4d0c1c6f
|
@ -147,7 +147,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
if (mapName.Length < 3 || (mapName.EndsWith("#") && mapName.Length < 4))
|
if (mapName.Length < 3 || (mapName.EndsWith("#") && mapName.Length < 4))
|
||||||
{
|
{
|
||||||
// final block, closing the search result
|
// final block, closing the search result
|
||||||
AddFinalBlock(blocks);
|
AddFinalBlock(blocks,mapName);
|
||||||
|
|
||||||
// flags are agent flags sent from the viewer.
|
// flags are agent flags sent from the viewer.
|
||||||
// they have different values depending on different viewers, apparently
|
// they have different values depending on different viewers, apparently
|
||||||
|
@ -211,8 +211,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
}
|
}
|
||||||
|
|
||||||
// final block, closing the search result
|
// final block, closing the search result
|
||||||
if(blocks.Count == 0)
|
AddFinalBlock(blocks,mapNameOrig);
|
||||||
AddFinalBlock(blocks);
|
|
||||||
|
|
||||||
// flags are agent flags sent from the viewer.
|
// flags are agent flags sent from the viewer.
|
||||||
// they have different values depending on different viewers, apparently
|
// they have different values depending on different viewers, apparently
|
||||||
|
@ -231,14 +230,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddFinalBlock(List<MapBlockData> blocks)
|
private void AddFinalBlock(List<MapBlockData> blocks,string name)
|
||||||
{
|
{
|
||||||
// final block, closing the search result
|
// final block, closing the search result
|
||||||
MapBlockData data = new MapBlockData();
|
MapBlockData data = new MapBlockData();
|
||||||
data.Agents = 0;
|
data.Agents = 0;
|
||||||
data.Access = (byte)SimAccess.NonExistent;
|
data.Access = (byte)SimAccess.NonExistent;
|
||||||
data.MapImageId = UUID.Zero;
|
data.MapImageId = UUID.Zero;
|
||||||
data.Name = "";
|
data.Name = name;
|
||||||
data.RegionFlags = 0;
|
data.RegionFlags = 0;
|
||||||
data.WaterHeight = 0; // not used
|
data.WaterHeight = 0; // not used
|
||||||
data.X = 0;
|
data.X = 0;
|
||||||
|
|
|
@ -68,9 +68,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
private static readonly UUID STOP_UUID = UUID.Random();
|
private static readonly UUID STOP_UUID = UUID.Random();
|
||||||
private static readonly string m_mapLayerPath = "0001/";
|
private static readonly string m_mapLayerPath = "0001/";
|
||||||
|
|
||||||
private ManualResetEvent queueEvent = new ManualResetEvent(false);
|
private OpenSim.Framework.BlockingQueue<MapRequestState> requests = new OpenSim.Framework.BlockingQueue<MapRequestState>();
|
||||||
private Queue<MapRequestState> requests = new Queue<MapRequestState>();
|
|
||||||
|
|
||||||
private ManualResetEvent m_mapBlockRequestEvent = new ManualResetEvent(false);
|
private ManualResetEvent m_mapBlockRequestEvent = new ManualResetEvent(false);
|
||||||
private Dictionary<UUID, Queue<MapBlockRequestData>> m_mapBlockRequests = new Dictionary<UUID, Queue<MapBlockRequestData>>();
|
private Dictionary<UUID, Queue<MapBlockRequestData>> m_mapBlockRequests = new Dictionary<UUID, Queue<MapBlockRequestData>>();
|
||||||
|
|
||||||
|
@ -79,16 +78,19 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
|
|
||||||
protected Scene m_scene;
|
protected Scene m_scene;
|
||||||
private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>();
|
private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>();
|
||||||
private int cachedTime = 0;
|
|
||||||
private int blacklistTimeout = 10 * 60 * 1000; // 10 minutes
|
|
||||||
private byte[] myMapImageJPEG;
|
private byte[] myMapImageJPEG;
|
||||||
protected volatile bool m_Enabled = false;
|
protected volatile bool m_Enabled = false;
|
||||||
private Dictionary<string, int> m_blacklistedurls = new Dictionary<string, int>();
|
private ExpiringCache<string, int> m_blacklistedurls = new ExpiringCache<string, int>();
|
||||||
private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>();
|
private ExpiringCache<ulong, int> m_blacklistedregions = new ExpiringCache<ulong, int>();
|
||||||
private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>();
|
private ExpiringCache<ulong, string> m_cachedRegionMapItemsAddress = new ExpiringCache<ulong, string>();
|
||||||
|
private ExpiringCache<ulong, OSDMap> m_cachedRegionMapItemsResponses =
|
||||||
|
new ExpiringCache<ulong, OSDMap>();
|
||||||
private List<UUID> m_rootAgents = new List<UUID>();
|
private List<UUID> m_rootAgents = new List<UUID>();
|
||||||
private volatile bool threadrunning = false;
|
private volatile bool threadrunning = false;
|
||||||
|
// expire time for the blacklists in seconds
|
||||||
|
private double expireBlackListTime = 600.0; // 10 minutes
|
||||||
|
// expire mapItems responses time in seconds. If too high disturbs the green dots updates
|
||||||
|
private const double expireResponsesTime = 120.0; // 2 minutes ?
|
||||||
//private int CacheRegionsDistance = 256;
|
//private int CacheRegionsDistance = 256;
|
||||||
|
|
||||||
#region INonSharedRegionModule Members
|
#region INonSharedRegionModule Members
|
||||||
|
@ -100,8 +102,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
config, "WorldMapModule", configSections, "WorldMap") == "WorldMap")
|
config, "WorldMapModule", configSections, "WorldMap") == "WorldMap")
|
||||||
m_Enabled = true;
|
m_Enabled = true;
|
||||||
|
|
||||||
blacklistTimeout
|
expireBlackListTime = (double)Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60);
|
||||||
= Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60) * 1000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void AddRegion(Scene scene)
|
public virtual void AddRegion(Scene scene)
|
||||||
|
@ -245,6 +246,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
public string MapLayerRequest(string request, string path, string param,
|
public string MapLayerRequest(string request, string path, string param,
|
||||||
UUID agentID, Caps caps)
|
UUID agentID, Caps caps)
|
||||||
{
|
{
|
||||||
|
// not sure about this....
|
||||||
|
|
||||||
//try
|
//try
|
||||||
//
|
//
|
||||||
//m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}",
|
//m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}",
|
||||||
|
@ -333,6 +336,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected static OSDMapLayer GetOSDMapLayerResponse()
|
protected static OSDMapLayer GetOSDMapLayerResponse()
|
||||||
{
|
{
|
||||||
|
// not sure about this.... 2048 or master 5000 and hack above?
|
||||||
|
|
||||||
OSDMapLayer mapLayer = new OSDMapLayer();
|
OSDMapLayer mapLayer = new OSDMapLayer();
|
||||||
mapLayer.Right = 2048;
|
mapLayer.Right = 2048;
|
||||||
mapLayer.Top = 2048;
|
mapLayer.Top = 2048;
|
||||||
|
@ -412,11 +417,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
st.itemtype = 0;
|
st.itemtype = 0;
|
||||||
st.regionhandle = 0;
|
st.regionhandle = 0;
|
||||||
|
|
||||||
lock (requests)
|
requests.Enqueue(st);
|
||||||
{
|
|
||||||
queueEvent.Set();
|
|
||||||
requests.Enqueue(st);
|
|
||||||
}
|
|
||||||
|
|
||||||
MapBlockRequestData req = new MapBlockRequestData();
|
MapBlockRequestData req = new MapBlockRequestData();
|
||||||
|
|
||||||
|
@ -599,55 +600,106 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
public void process()
|
public void process()
|
||||||
{
|
{
|
||||||
const int MAX_ASYNC_REQUESTS = 20;
|
const int MAX_ASYNC_REQUESTS = 20;
|
||||||
|
ScenePresence av = null;
|
||||||
|
MapRequestState st = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
MapRequestState st = new MapRequestState();
|
Watchdog.UpdateThread();
|
||||||
bool valid = false;
|
|
||||||
queueEvent.WaitOne();
|
av = null;
|
||||||
lock (requests)
|
st = null;
|
||||||
{
|
|
||||||
if (requests.Count > 0)
|
st = requests.Dequeue(4900); // timeout to make watchdog happy
|
||||||
{
|
|
||||||
st = requests.Dequeue();
|
if (st == null || st.agentID == UUID.Zero)
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
if (requests.Count == 0)
|
|
||||||
queueEvent.Reset();
|
|
||||||
}
|
|
||||||
if (!valid)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// end gracefully
|
// end gracefully
|
||||||
if (st.agentID == STOP_UUID)
|
if (st.agentID == STOP_UUID)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (st.agentID != UUID.Zero)
|
// agent gone?
|
||||||
|
|
||||||
|
m_scene.TryGetScenePresence(st.agentID, out av);
|
||||||
|
if (av == null || av.IsChildAgent || av.IsDeleted || av.IsInTransit)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// region unreachable?
|
||||||
|
if (m_blacklistedregions.Contains(st.regionhandle))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool dorequest = true;
|
||||||
|
OSDMap responseMap = null;
|
||||||
|
|
||||||
|
// check if we are already serving this region
|
||||||
|
lock (m_cachedRegionMapItemsResponses)
|
||||||
{
|
{
|
||||||
bool dorequest = true;
|
if (m_cachedRegionMapItemsResponses.Contains(st.regionhandle))
|
||||||
lock (m_rootAgents)
|
|
||||||
{
|
{
|
||||||
if (!m_rootAgents.Contains(st.agentID))
|
m_cachedRegionMapItemsResponses.TryGetValue(st.regionhandle, out responseMap);
|
||||||
dorequest = false;
|
dorequest = false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
m_cachedRegionMapItemsResponses.Add(st.regionhandle, null, expireResponsesTime); // a bit more time for the access
|
||||||
|
}
|
||||||
|
|
||||||
if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle))
|
if (dorequest)
|
||||||
|
{
|
||||||
|
// nothig for region, fire a request
|
||||||
|
Interlocked.Increment(ref nAsyncRequests);
|
||||||
|
MapRequestState rst = st;
|
||||||
|
Util.FireAndForget(x =>
|
||||||
{
|
{
|
||||||
while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
|
RequestMapItemsAsync(rst.agentID, rst.flags, rst.EstateID, rst.godlike, rst.itemtype, rst.regionhandle);
|
||||||
Thread.Sleep(100);
|
});
|
||||||
|
}
|
||||||
Interlocked.Increment(ref nAsyncRequests);
|
else
|
||||||
Util.FireAndForget(x =>
|
{
|
||||||
|
// do we have the response?
|
||||||
|
if (responseMap != null)
|
||||||
|
{
|
||||||
|
if(av!=null)
|
||||||
{
|
{
|
||||||
RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
|
if (responseMap.ContainsKey(st.itemtype.ToString()))
|
||||||
});
|
{
|
||||||
|
List<mapItemReply> returnitems = new List<mapItemReply>();
|
||||||
|
OSDArray itemarray = (OSDArray)responseMap[st.itemtype.ToString()];
|
||||||
|
for (int i = 0; i < itemarray.Count; i++)
|
||||||
|
{
|
||||||
|
OSDMap mapitem = (OSDMap)itemarray[i];
|
||||||
|
mapItemReply mi = new mapItemReply();
|
||||||
|
mi.x = (uint)mapitem["X"].AsInteger();
|
||||||
|
mi.y = (uint)mapitem["Y"].AsInteger();
|
||||||
|
mi.id = mapitem["ID"].AsUUID();
|
||||||
|
mi.Extra = mapitem["Extra"].AsInteger();
|
||||||
|
mi.Extra2 = mapitem["Extra2"].AsInteger();
|
||||||
|
mi.name = mapitem["Name"].AsString();
|
||||||
|
returnitems.Add(mi);
|
||||||
|
}
|
||||||
|
av.ControllingClient.SendMapItemReply(returnitems.ToArray(), st.itemtype, st.flags & 0xffff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// request still beeing processed, enqueue it back
|
||||||
|
requests.Enqueue(st);
|
||||||
|
if (requests.Count() < 3)
|
||||||
|
Thread.Sleep(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Watchdog.UpdateThread();
|
while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
|
||||||
|
{
|
||||||
|
Thread.Sleep(100);
|
||||||
|
Watchdog.UpdateThread();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.ErrorFormat("[WORLD MAP]: Map item request thread terminated abnormally with exception {0}", e);
|
m_log.ErrorFormat("[WORLD MAP]: Map item request thread terminated abnormally with exception {0}", e);
|
||||||
|
@ -657,20 +709,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
Watchdog.RemoveThread();
|
Watchdog.RemoveThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enqueues the map item request into the processing thread
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="state"></param>
|
|
||||||
public void EnqueueMapItemRequest(MapRequestState state)
|
|
||||||
{
|
|
||||||
lock (requests)
|
|
||||||
{
|
|
||||||
queueEvent.Set();
|
|
||||||
requests.Enqueue(state);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enqueue the MapItem request for remote processing
|
/// Enqueue the MapItem request for remote processing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -691,7 +729,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
st.godlike = godlike;
|
st.godlike = godlike;
|
||||||
st.itemtype = itemtype;
|
st.itemtype = itemtype;
|
||||||
st.regionhandle = regionhandle;
|
st.regionhandle = regionhandle;
|
||||||
EnqueueMapItemRequest(st);
|
|
||||||
|
requests.Enqueue(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -711,24 +750,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
private void RequestMapItemsAsync(UUID id, uint flags,
|
private void RequestMapItemsAsync(UUID id, uint flags,
|
||||||
uint EstateID, bool godlike, uint itemtype, ulong regionhandle)
|
uint EstateID, bool godlike, uint itemtype, ulong regionhandle)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype);
|
// m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype);
|
||||||
|
|
||||||
string httpserver = "";
|
string httpserver = "";
|
||||||
bool blacklisted = false;
|
bool blacklisted = false;
|
||||||
lock (m_blacklistedregions)
|
|
||||||
{
|
|
||||||
if (m_blacklistedregions.ContainsKey(regionhandle))
|
|
||||||
{
|
|
||||||
if (Environment.TickCount > (m_blacklistedregions[regionhandle] + blacklistTimeout))
|
|
||||||
{
|
|
||||||
m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted region {0}", regionhandle);
|
|
||||||
|
|
||||||
m_blacklistedregions.Remove(regionhandle);
|
lock (m_blacklistedregions)
|
||||||
}
|
blacklisted = m_blacklistedregions.Contains(regionhandle);
|
||||||
else
|
|
||||||
blacklisted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blacklisted)
|
if (blacklisted)
|
||||||
{
|
{
|
||||||
|
@ -738,60 +766,36 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
|
|
||||||
UUID requestID = UUID.Random();
|
UUID requestID = UUID.Random();
|
||||||
lock (m_cachedRegionMapItemsAddress)
|
lock (m_cachedRegionMapItemsAddress)
|
||||||
{
|
m_cachedRegionMapItemsAddress.TryGetValue(regionhandle, out httpserver);
|
||||||
if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle))
|
|
||||||
httpserver = m_cachedRegionMapItemsAddress[regionhandle];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (httpserver.Length == 0)
|
if (httpserver == null || httpserver.Length == 0)
|
||||||
{
|
{
|
||||||
uint x = 0, y = 0;
|
uint x = 0, y = 0;
|
||||||
Util.RegionHandleToWorldLoc(regionhandle, out x, out y);
|
Util.RegionHandleToWorldLoc(regionhandle, out x, out y);
|
||||||
|
|
||||||
GridRegion mreg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
|
GridRegion mreg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
|
||||||
|
|
||||||
if (mreg != null)
|
if (mreg != null)
|
||||||
{
|
{
|
||||||
httpserver = mreg.ServerURI + "MAP/MapItems/" + regionhandle.ToString();
|
httpserver = mreg.ServerURI + "MAP/MapItems/" + regionhandle.ToString();
|
||||||
lock (m_cachedRegionMapItemsAddress)
|
lock (m_cachedRegionMapItemsAddress)
|
||||||
{
|
m_cachedRegionMapItemsAddress.AddOrUpdate(regionhandle, httpserver, 2.0 * expireBlackListTime);
|
||||||
if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle))
|
|
||||||
m_cachedRegionMapItemsAddress.Add(regionhandle, httpserver);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lock (m_blacklistedregions)
|
|
||||||
{
|
|
||||||
if (!m_blacklistedregions.ContainsKey(regionhandle))
|
|
||||||
m_blacklistedregions.Add(regionhandle, Environment.TickCount);
|
|
||||||
}
|
|
||||||
//m_log.InfoFormat("[WORLD MAP]: Blacklisted region {0}", regionhandle.ToString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
blacklisted = false;
|
|
||||||
lock (m_blacklistedurls)
|
lock (m_blacklistedurls)
|
||||||
{
|
{
|
||||||
if (m_blacklistedurls.ContainsKey(httpserver))
|
if (httpserver == null || httpserver.Length == 0 || m_blacklistedurls.Contains(httpserver))
|
||||||
{
|
{
|
||||||
if (Environment.TickCount > (m_blacklistedurls[httpserver] + blacklistTimeout))
|
// Can't find the http server or its blocked
|
||||||
{
|
lock (m_blacklistedregions)
|
||||||
m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted URL {0}", httpserver);
|
m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
|
||||||
|
|
||||||
m_blacklistedurls.Remove(httpserver);
|
Interlocked.Decrement(ref nAsyncRequests);
|
||||||
}
|
return;
|
||||||
else
|
|
||||||
blacklisted = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can't find the http server
|
|
||||||
if (httpserver.Length == 0 || blacklisted)
|
|
||||||
{
|
|
||||||
Interlocked.Decrement(ref nAsyncRequests);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WebRequest mapitemsrequest = null;
|
WebRequest mapitemsrequest = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -806,34 +810,30 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
|
|
||||||
mapitemsrequest.Method = "POST";
|
mapitemsrequest.Method = "POST";
|
||||||
mapitemsrequest.ContentType = "application/xml+llsd";
|
mapitemsrequest.ContentType = "application/xml+llsd";
|
||||||
OSDMap RAMap = new OSDMap();
|
|
||||||
|
|
||||||
|
OSDMap RAMap = new OSDMap();
|
||||||
// string RAMapString = RAMap.ToString();
|
// string RAMapString = RAMap.ToString();
|
||||||
OSD LLSDofRAMap = RAMap; // RENAME if this works
|
OSD LLSDofRAMap = RAMap; // RENAME if this works
|
||||||
|
|
||||||
byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap);
|
byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap);
|
||||||
OSDMap responseMap = new OSDMap();
|
|
||||||
responseMap["requestID"] = OSD.FromUUID(requestID);
|
|
||||||
|
|
||||||
Stream os = null;
|
OSDMap responseMap = new OSDMap();
|
||||||
|
|
||||||
try
|
try
|
||||||
{ // send the Post
|
{ // send the Post
|
||||||
mapitemsrequest.ContentLength = buffer.Length; //Count bytes to send
|
mapitemsrequest.ContentLength = buffer.Length; //Count bytes to send
|
||||||
os = mapitemsrequest.GetRequestStream();
|
using (Stream os = mapitemsrequest.GetRequestStream())
|
||||||
os.Write(buffer, 0, buffer.Length); //Send it
|
os.Write(buffer, 0, buffer.Length); //Send it
|
||||||
//m_log.DebugFormat("[WORLD MAP]: Getting MapItems from {0}", httpserver);
|
//m_log.DebugFormat("[WORLD MAP]: Getting MapItems from {0}", httpserver);
|
||||||
}
|
}
|
||||||
catch (WebException ex)
|
catch (WebException ex)
|
||||||
{
|
{
|
||||||
m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message);
|
m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message);
|
||||||
responseMap["connect"] = OSD.FromBoolean(false);
|
m_log.WarnFormat("[WORLD MAP]: Blacklisted url {0}", httpserver);
|
||||||
lock (m_blacklistedurls)
|
lock (m_blacklistedurls)
|
||||||
{
|
m_blacklistedurls.AddOrUpdate(httpserver, 0, expireBlackListTime);
|
||||||
if (!m_blacklistedurls.ContainsKey(httpserver))
|
lock (m_blacklistedregions)
|
||||||
m_blacklistedurls.Add(httpserver, Environment.TickCount);
|
m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
|
||||||
}
|
|
||||||
|
|
||||||
m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
|
|
||||||
|
|
||||||
Interlocked.Decrement(ref nAsyncRequests);
|
Interlocked.Decrement(ref nAsyncRequests);
|
||||||
return;
|
return;
|
||||||
|
@ -844,11 +844,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
Interlocked.Decrement(ref nAsyncRequests);
|
Interlocked.Decrement(ref nAsyncRequests);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (os != null)
|
|
||||||
os.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
string response_mapItems_reply = null;
|
string response_mapItems_reply = null;
|
||||||
{ // get the response
|
{ // get the response
|
||||||
|
@ -873,12 +868,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
catch (WebException)
|
catch (WebException)
|
||||||
{
|
{
|
||||||
lock (m_blacklistedurls)
|
lock (m_blacklistedurls)
|
||||||
{
|
m_blacklistedurls.AddOrUpdate(httpserver, 0, expireBlackListTime);
|
||||||
if (!m_blacklistedurls.ContainsKey(httpserver))
|
lock (m_blacklistedregions)
|
||||||
m_blacklistedurls.Add(httpserver, Environment.TickCount);
|
m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
|
||||||
}
|
|
||||||
|
|
||||||
m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
|
m_log.WarnFormat("[WORLD MAP]: Blacklisted url {0}", httpserver);
|
||||||
|
|
||||||
Interlocked.Decrement(ref nAsyncRequests);
|
Interlocked.Decrement(ref nAsyncRequests);
|
||||||
return;
|
return;
|
||||||
|
@ -887,46 +881,39 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
|
m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
|
||||||
lock (m_blacklistedregions)
|
lock (m_blacklistedregions)
|
||||||
{
|
m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
|
||||||
if (!m_blacklistedregions.ContainsKey(regionhandle))
|
|
||||||
m_blacklistedregions.Add(regionhandle, Environment.TickCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
Interlocked.Decrement(ref nAsyncRequests);
|
Interlocked.Decrement(ref nAsyncRequests);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OSD rezResponse = null;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
rezResponse = OSDParser.DeserializeLLSDXml(response_mapItems_reply);
|
responseMap = (OSDMap)OSDParser.DeserializeLLSDXml(response_mapItems_reply);
|
||||||
|
|
||||||
responseMap = (OSDMap)rezResponse;
|
|
||||||
responseMap["requestID"] = OSD.FromUUID(requestID);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message);
|
m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message);
|
||||||
lock (m_blacklistedregions)
|
lock (m_blacklistedregions)
|
||||||
{
|
m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
|
||||||
if (!m_blacklistedregions.ContainsKey(regionhandle))
|
|
||||||
m_blacklistedregions.Add(regionhandle, Environment.TickCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
Interlocked.Decrement(ref nAsyncRequests);
|
Interlocked.Decrement(ref nAsyncRequests);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Interlocked.Decrement(ref nAsyncRequests);
|
// cache the response that may include other valid items
|
||||||
|
lock (m_cachedRegionMapItemsResponses)
|
||||||
|
m_cachedRegionMapItemsResponses.AddOrUpdate(regionhandle, responseMap, expireResponsesTime);
|
||||||
|
|
||||||
|
// send answer for this item and client
|
||||||
flags &= 0xffff;
|
flags &= 0xffff;
|
||||||
|
|
||||||
if (id != UUID.Zero)
|
if (id != UUID.Zero)
|
||||||
{
|
{
|
||||||
ScenePresence av = null;
|
ScenePresence av = null;
|
||||||
m_scene.TryGetScenePresence(id, out av);
|
m_scene.TryGetScenePresence(id, out av);
|
||||||
if (av != null)
|
if (av != null && !av.IsChildAgent && !av.IsDeleted && !av.IsInTransit)
|
||||||
{
|
{
|
||||||
if (responseMap.ContainsKey(itemtype.ToString()))
|
if (responseMap.ContainsKey(itemtype.ToString()))
|
||||||
{
|
{
|
||||||
|
@ -946,54 +933,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
}
|
}
|
||||||
av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
|
av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send things viewer didn't ask ?
|
|
||||||
// Service 7 (MAP_ITEM_LAND_FOR_SALE)
|
|
||||||
itemtype = 7;
|
|
||||||
|
|
||||||
if (responseMap.ContainsKey(itemtype.ToString()))
|
|
||||||
{
|
|
||||||
List<mapItemReply> returnitems = new List<mapItemReply>();
|
|
||||||
OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
|
|
||||||
for (int i = 0; i < itemarray.Count; i++)
|
|
||||||
{
|
|
||||||
OSDMap mapitem = (OSDMap)itemarray[i];
|
|
||||||
mapItemReply mi = new mapItemReply();
|
|
||||||
mi.x = (uint)mapitem["X"].AsInteger();
|
|
||||||
mi.y = (uint)mapitem["Y"].AsInteger();
|
|
||||||
mi.id = mapitem["ID"].AsUUID();
|
|
||||||
mi.Extra = mapitem["Extra"].AsInteger();
|
|
||||||
mi.Extra2 = mapitem["Extra2"].AsInteger();
|
|
||||||
mi.name = mapitem["Name"].AsString();
|
|
||||||
returnitems.Add(mi);
|
|
||||||
}
|
|
||||||
av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Service 1 (MAP_ITEM_TELEHUB)
|
|
||||||
itemtype = 1;
|
|
||||||
|
|
||||||
if (responseMap.ContainsKey(itemtype.ToString()))
|
|
||||||
{
|
|
||||||
List<mapItemReply> returnitems = new List<mapItemReply>();
|
|
||||||
OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
|
|
||||||
for (int i = 0; i < itemarray.Count; i++)
|
|
||||||
{
|
|
||||||
OSDMap mapitem = (OSDMap)itemarray[i];
|
|
||||||
mapItemReply mi = new mapItemReply();
|
|
||||||
mi.x = (uint)mapitem["X"].AsInteger();
|
|
||||||
mi.y = (uint)mapitem["Y"].AsInteger();
|
|
||||||
mi.id = mapitem["ID"].AsUUID();
|
|
||||||
mi.Extra = mapitem["Extra"].AsInteger();
|
|
||||||
mi.Extra2 = mapitem["Extra2"].AsInteger();
|
|
||||||
mi.name = mapitem["Name"].AsString();
|
|
||||||
returnitems.Add(mi);
|
|
||||||
}
|
|
||||||
av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Interlocked.Decrement(ref nAsyncRequests);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1160,67 +1103,71 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
|
|
||||||
public Hashtable OnHTTPGetMapImage(Hashtable keysvals)
|
public Hashtable OnHTTPGetMapImage(Hashtable keysvals)
|
||||||
{
|
{
|
||||||
m_log.Debug("[WORLD MAP]: Sending map image jpeg");
|
|
||||||
Hashtable reply = new Hashtable();
|
Hashtable reply = new Hashtable();
|
||||||
int statuscode = 200;
|
int statuscode = 200;
|
||||||
byte[] jpeg = new byte[0];
|
byte[] jpeg = new byte[0];
|
||||||
|
|
||||||
if (myMapImageJPEG.Length == 0)
|
if (m_scene.RegionInfo.RegionSettings.TerrainImageID != UUID.Zero)
|
||||||
{
|
{
|
||||||
MemoryStream imgstream = null;
|
m_log.Debug("[WORLD MAP]: Sending map image jpeg");
|
||||||
Bitmap mapTexture = new Bitmap(1, 1);
|
|
||||||
ManagedImage managedImage;
|
|
||||||
Image image = (Image)mapTexture;
|
|
||||||
|
|
||||||
try
|
if (myMapImageJPEG.Length == 0)
|
||||||
{
|
{
|
||||||
// Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data
|
MemoryStream imgstream = null;
|
||||||
|
Bitmap mapTexture = new Bitmap(1, 1);
|
||||||
|
ManagedImage managedImage;
|
||||||
|
Image image = (Image)mapTexture;
|
||||||
|
|
||||||
imgstream = new MemoryStream();
|
try
|
||||||
|
|
||||||
// non-async because we know we have the asset immediately.
|
|
||||||
AssetBase mapasset = m_scene.AssetService.Get(m_scene.RegionInfo.RegionSettings.TerrainImageID.ToString());
|
|
||||||
|
|
||||||
// Decode image to System.Drawing.Image
|
|
||||||
if (OpenJPEG.DecodeToImage(mapasset.Data, out managedImage, out image))
|
|
||||||
{
|
{
|
||||||
// Save to bitmap
|
// Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data
|
||||||
mapTexture = new Bitmap(image);
|
|
||||||
|
|
||||||
EncoderParameters myEncoderParameters = new EncoderParameters();
|
imgstream = new MemoryStream();
|
||||||
myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L);
|
|
||||||
|
|
||||||
// Save bitmap to stream
|
// non-async because we know we have the asset immediately.
|
||||||
mapTexture.Save(imgstream, GetEncoderInfo("image/jpeg"), myEncoderParameters);
|
AssetBase mapasset = m_scene.AssetService.Get(m_scene.RegionInfo.RegionSettings.TerrainImageID.ToString());
|
||||||
|
|
||||||
// Write the stream to a byte array for output
|
// Decode image to System.Drawing.Image
|
||||||
jpeg = imgstream.ToArray();
|
if (OpenJPEG.DecodeToImage(mapasset.Data, out managedImage, out image))
|
||||||
myMapImageJPEG = jpeg;
|
{
|
||||||
|
// Save to bitmap
|
||||||
|
mapTexture = new Bitmap(image);
|
||||||
|
|
||||||
|
EncoderParameters myEncoderParameters = new EncoderParameters();
|
||||||
|
myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L);
|
||||||
|
|
||||||
|
// Save bitmap to stream
|
||||||
|
mapTexture.Save(imgstream, GetEncoderInfo("image/jpeg"), myEncoderParameters);
|
||||||
|
|
||||||
|
// Write the stream to a byte array for output
|
||||||
|
jpeg = imgstream.ToArray();
|
||||||
|
myMapImageJPEG = jpeg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// Dummy!
|
||||||
|
m_log.Warn("[WORLD MAP]: Unable to generate Map image");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Reclaim memory, these are unmanaged resources
|
||||||
|
// If we encountered an exception, one or more of these will be null
|
||||||
|
if (mapTexture != null)
|
||||||
|
mapTexture.Dispose();
|
||||||
|
|
||||||
|
if (image != null)
|
||||||
|
image.Dispose();
|
||||||
|
|
||||||
|
if (imgstream != null)
|
||||||
|
imgstream.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception)
|
else
|
||||||
{
|
{
|
||||||
// Dummy!
|
// Use cached version so we don't have to loose our mind
|
||||||
m_log.Warn("[WORLD MAP]: Unable to generate Map image");
|
jpeg = myMapImageJPEG;
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
// Reclaim memory, these are unmanaged resources
|
|
||||||
// If we encountered an exception, one or more of these will be null
|
|
||||||
if (mapTexture != null)
|
|
||||||
mapTexture.Dispose();
|
|
||||||
|
|
||||||
if (image != null)
|
|
||||||
image.Dispose();
|
|
||||||
|
|
||||||
if (imgstream != null)
|
|
||||||
imgstream.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Use cached version so we don't have to loose our mind
|
|
||||||
jpeg = myMapImageJPEG;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reply["str_response_string"] = Convert.ToBase64String(jpeg);
|
reply["str_response_string"] = Convert.ToBase64String(jpeg);
|
||||||
|
@ -1290,15 +1237,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
{
|
{
|
||||||
textures.Add(texAsset);
|
textures.Add(texAsset);
|
||||||
}
|
}
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// // WHAT?!? This doesn't seem right. Commenting (diva)
|
|
||||||
// texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString());
|
|
||||||
// if (texAsset != null)
|
|
||||||
// {
|
|
||||||
// textures.Add(texAsset);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (AssetBase asset in textures)
|
foreach (AssetBase asset in textures)
|
||||||
|
@ -1338,26 +1276,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
|
|
||||||
GenerateMaptile();
|
GenerateMaptile();
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
if (m_mapImageGenerator == null)
|
|
||||||
{
|
|
||||||
Console.WriteLine("No map image generator available for {0}", m_scene.Name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTile())
|
|
||||||
{
|
|
||||||
GenerateMaptile(mapbmp);
|
|
||||||
if(m_mapImageServiceModule != null)
|
|
||||||
m_mapImageServiceModule.UploadMapTile(m_scene, mapbmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint)
|
public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint)
|
||||||
{
|
{
|
||||||
uint xstart = 0;
|
uint xstart = 0;
|
||||||
uint ystart = 0;
|
uint ystart = 0;
|
||||||
|
|
||||||
|
// create and send back answers about all items active
|
||||||
|
// so call region can cache them and answer to the several
|
||||||
|
// individual item viewer requests
|
||||||
|
|
||||||
Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart);
|
Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart);
|
||||||
|
|
||||||
// Service 6 (MAP_ITEM_AGENTS_LOCATION; green dots)
|
// Service 6 (MAP_ITEM_AGENTS_LOCATION; green dots)
|
||||||
|
@ -1605,20 +1533,20 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
|
|
||||||
lock (m_blacklistedregions)
|
lock (m_blacklistedregions)
|
||||||
{
|
{
|
||||||
if (!m_blacklistedregions.ContainsKey(regionhandle))
|
if (m_blacklistedregions.Contains(regionhandle))
|
||||||
m_blacklistedregions.Remove(regionhandle);
|
m_blacklistedregions.Remove(regionhandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (m_blacklistedurls)
|
lock (m_blacklistedurls)
|
||||||
{
|
{
|
||||||
if (m_blacklistedurls.ContainsKey(httpserver))
|
if (m_blacklistedurls.Contains(httpserver))
|
||||||
m_blacklistedurls.Remove(httpserver);
|
m_blacklistedurls.Remove(httpserver);
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (m_cachedRegionMapItemsAddress)
|
lock (m_cachedRegionMapItemsAddress)
|
||||||
{
|
{
|
||||||
if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle))
|
m_cachedRegionMapItemsAddress.AddOrUpdate(regionhandle,
|
||||||
m_cachedRegionMapItemsAddress.Remove(regionhandle);
|
httpserver, 5.0 * expireBlackListTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1706,7 +1634,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct MapRequestState
|
public class MapRequestState
|
||||||
{
|
{
|
||||||
public UUID agentID;
|
public UUID agentID;
|
||||||
public uint flags;
|
public uint flags;
|
||||||
|
|
Loading…
Reference in New Issue