Merge branch 'avination' into ubitwork

avinationmerge
UbitUmarov 2012-07-08 13:09:32 +01:00
commit b74d4711bb
6 changed files with 408 additions and 281 deletions

View File

@ -90,9 +90,9 @@ namespace OpenSim.Region.CoreModules.Hypergrid
} }
} }
protected override List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) protected override List<MapBlockData> GetAndSendBlocksInternal(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
{ {
List<MapBlockData> mapBlocks = base.GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag); List<MapBlockData> mapBlocks = base.GetAndSendBlocksInternal(remoteClient, minX, minY, maxX, maxY, flag);
lock (m_SeenMapBlocks) lock (m_SeenMapBlocks)
{ {
if (!m_SeenMapBlocks.ContainsKey(remoteClient.AgentId)) if (!m_SeenMapBlocks.ContainsKey(remoteClient.AgentId))

View File

@ -86,90 +86,93 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags) private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags)
{ {
if (mapName.Length < 2) Util.FireAndForget(x =>
{ {
remoteClient.SendAlertMessage("Use a search string with at least 2 characters"); if (mapName.Length < 2)
return;
}
//m_log.DebugFormat("MAP NAME=({0})", mapName);
// Hack to get around the fact that ll V3 now drops the port from the
// map name. See https://jira.secondlife.com/browse/VWR-28570
//
// Caller, use this magic form instead:
// secondlife://http|!!mygrid.com|8002|Region+Name/128/128
// or url encode if possible.
// the hacks we do with this viewer...
//
string mapNameOrig = mapName;
if (mapName.Contains("|"))
mapName = mapName.Replace('|', ':');
if (mapName.Contains("+"))
mapName = mapName.Replace('+', ' ');
if (mapName.Contains("!"))
mapName = mapName.Replace('!', '/');
// try to fetch from GridServer
List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);
// if (regionInfos.Count == 0)
// remoteClient.SendAlertMessage("Hyperlink could not be established.");
//m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions", mapName, regionInfos.Count);
List<MapBlockData> blocks = new List<MapBlockData>();
MapBlockData data;
if (regionInfos.Count > 0)
{
foreach (GridRegion info in regionInfos)
{ {
data = new MapBlockData(); remoteClient.SendAlertMessage("Use a search string with at least 2 characters");
data.Agents = 0; return;
data.Access = info.Access;
if (flags == 2) // V2 sends this
data.MapImageId = UUID.Zero;
else
data.MapImageId = info.TerrainImage;
// ugh! V2-3 is very sensitive about the result being
// exactly the same as the requested name
if (regionInfos.Count == 1 && mapNameOrig.Contains("|") || mapNameOrig.Contains("+"))
data.Name = mapNameOrig;
else
data.Name = info.RegionName;
data.RegionFlags = 0; // TODO not used?
data.WaterHeight = 0; // not used
data.X = (ushort)(info.RegionLocX / Constants.RegionSize);
data.Y = (ushort)(info.RegionLocY / Constants.RegionSize);
blocks.Add(data);
} }
}
// final block, closing the search result //m_log.DebugFormat("MAP NAME=({0})", mapName);
data = new MapBlockData();
data.Agents = 0;
data.Access = 255;
data.MapImageId = UUID.Zero;
data.Name = mapName;
data.RegionFlags = 0;
data.WaterHeight = 0; // not used
data.X = 0;
data.Y = 0;
blocks.Add(data);
// flags are agent flags sent from the viewer. // Hack to get around the fact that ll V3 now drops the port from the
// they have different values depending on different viewers, apparently // map name. See https://jira.secondlife.com/browse/VWR-28570
remoteClient.SendMapBlock(blocks, flags); //
// Caller, use this magic form instead:
// secondlife://http|!!mygrid.com|8002|Region+Name/128/128
// or url encode if possible.
// the hacks we do with this viewer...
//
string mapNameOrig = mapName;
if (mapName.Contains("|"))
mapName = mapName.Replace('|', ':');
if (mapName.Contains("+"))
mapName = mapName.Replace('+', ' ');
if (mapName.Contains("!"))
mapName = mapName.Replace('!', '/');
// try to fetch from GridServer
List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);
// if (regionInfos.Count == 0)
// remoteClient.SendAlertMessage("Hyperlink could not be established.");
// send extra user messages for V3 //m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions", mapName, regionInfos.Count);
// because the UI is very confusing List<MapBlockData> blocks = new List<MapBlockData>();
// while we don't fix the hard-coded urls
if (flags == 2) MapBlockData data;
{ if (regionInfos.Count > 0)
if (regionInfos.Count == 0) {
remoteClient.SendAgentAlertMessage("No regions found with that name.", true); foreach (GridRegion info in regionInfos)
else if (regionInfos.Count == 1) {
remoteClient.SendAgentAlertMessage("Region found!", false); data = new MapBlockData();
} data.Agents = 0;
data.Access = info.Access;
if (flags == 2) // V2 sends this
data.MapImageId = UUID.Zero;
else
data.MapImageId = info.TerrainImage;
// ugh! V2-3 is very sensitive about the result being
// exactly the same as the requested name
if (regionInfos.Count == 1 && mapNameOrig.Contains("|") || mapNameOrig.Contains("+"))
data.Name = mapNameOrig;
else
data.Name = info.RegionName;
data.RegionFlags = 0; // TODO not used?
data.WaterHeight = 0; // not used
data.X = (ushort)(info.RegionLocX / Constants.RegionSize);
data.Y = (ushort)(info.RegionLocY / Constants.RegionSize);
blocks.Add(data);
}
}
// final block, closing the search result
data = new MapBlockData();
data.Agents = 0;
data.Access = 255;
data.MapImageId = UUID.Zero;
data.Name = mapName;
data.RegionFlags = 0;
data.WaterHeight = 0; // not used
data.X = 0;
data.Y = 0;
blocks.Add(data);
// flags are agent flags sent from the viewer.
// they have different values depending on different viewers, apparently
remoteClient.SendMapBlock(blocks, flags);
// send extra user messages for V3
// because the UI is very confusing
// while we don't fix the hard-coded urls
if (flags == 2)
{
if (regionInfos.Count == 0)
remoteClient.SendAgentAlertMessage("No regions found with that name.", true);
else if (regionInfos.Count == 1)
remoteClient.SendAgentAlertMessage("Region found!", false);
}
});
} }
// private Scene GetClientScene(IClientAPI client) // private Scene GetClientScene(IClientAPI client)

View File

@ -63,7 +63,11 @@ 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 OpenSim.Framework.BlockingQueue<MapRequestState> requests = new OpenSim.Framework.BlockingQueue<MapRequestState>(); private ManualResetEvent queueEvent = new ManualResetEvent(false);
private Queue<MapRequestState> requests = new Queue<MapRequestState>();
private ManualResetEvent m_mapBlockRequestEvent = new ManualResetEvent(false);
private Dictionary<UUID, Queue<MapBlockRequestData>> m_mapBlockRequests = new Dictionary<UUID, Queue<MapBlockRequestData>>();
protected Scene m_scene; protected Scene m_scene;
private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>(); private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>();
@ -71,7 +75,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
private int blacklistTimeout = 10*60*1000; // 10 minutes 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<UUID, MapRequestState> m_openRequests = new Dictionary<UUID, MapRequestState>();
private Dictionary<string, int> m_blacklistedurls = new Dictionary<string, int>(); private Dictionary<string, int> m_blacklistedurls = new Dictionary<string, int>();
private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>(); private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>();
private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>(); private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>();
@ -227,54 +230,54 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
// 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is
// a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks. // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks.
if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048) //if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048)
{ //{
ScenePresence avatarPresence = null; // ScenePresence avatarPresence = null;
m_scene.TryGetScenePresence(agentID, out avatarPresence); // m_scene.TryGetScenePresence(agentID, out avatarPresence);
if (avatarPresence != null) // if (avatarPresence != null)
{ // {
bool lookup = false; // bool lookup = false;
lock (cachedMapBlocks) // lock (cachedMapBlocks)
{ // {
if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) // if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch()))
{ // {
List<MapBlockData> mapBlocks; // List<MapBlockData> mapBlocks;
mapBlocks = cachedMapBlocks; // mapBlocks = cachedMapBlocks;
avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
} // }
else // else
{ // {
lookup = true; // lookup = true;
} // }
} // }
if (lookup) // if (lookup)
{ // {
List<MapBlockData> mapBlocks = new List<MapBlockData>(); ; // List<MapBlockData> mapBlocks = new List<MapBlockData>(); ;
List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, // List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
(int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize, // (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize,
(int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize, // (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize,
(int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize, // (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize,
(int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize); // (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize);
foreach (GridRegion r in regions) // foreach (GridRegion r in regions)
{ // {
MapBlockData block = new MapBlockData(); // MapBlockData block = new MapBlockData();
MapBlockFromGridRegion(block, r, 0); // MapBlockFromGridRegion(block, r, 0);
mapBlocks.Add(block); // mapBlocks.Add(block);
} // }
avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
lock (cachedMapBlocks) // lock (cachedMapBlocks)
cachedMapBlocks = mapBlocks; // cachedMapBlocks = mapBlocks;
cachedTime = Util.UnixTimeSinceEpoch(); // cachedTime = Util.UnixTimeSinceEpoch();
} // }
} // }
} //}
LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
@ -301,8 +304,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
protected static OSDMapLayer GetOSDMapLayerResponse() protected static OSDMapLayer GetOSDMapLayerResponse()
{ {
OSDMapLayer mapLayer = new OSDMapLayer(); OSDMapLayer mapLayer = new OSDMapLayer();
mapLayer.Right = 5000; mapLayer.Right = 2048;
mapLayer.Top = 5000; mapLayer.Top = 2048;
mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006"); mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006");
return mapLayer; return mapLayer;
@ -331,6 +334,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
{ {
m_rootAgents.Remove(AgentId); m_rootAgents.Remove(AgentId);
} }
lock (m_mapBlockRequestEvent)
{
if (m_mapBlockRequests.ContainsKey(AgentId))
m_mapBlockRequests.Remove(AgentId);
}
} }
#endregion #endregion
@ -353,6 +361,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
ThreadPriority.BelowNormal, ThreadPriority.BelowNormal,
true, true,
true); true);
Watchdog.StartThread(
MapBlockSendThread,
string.Format("MapBlockSendThread ({0})", m_scene.RegionInfo.RegionName),
ThreadPriority.BelowNormal,
true,
true);
} }
/// <summary> /// <summary>
@ -368,7 +382,27 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
st.itemtype=0; st.itemtype=0;
st.regionhandle=0; st.regionhandle=0;
requests.Enqueue(st); lock (requests)
{
queueEvent.Set();
requests.Enqueue(st);
}
MapBlockRequestData req = new MapBlockRequestData();
req.client = null;
req.minX = 0;
req.maxX = 0;
req.minY = 0;
req.maxY = 0;
req.flags = 0;
lock (m_mapBlockRequestEvent)
{
m_mapBlockRequests[UUID.Zero] = new Queue<MapBlockRequestData>();
m_mapBlockRequests[UUID.Zero].Enqueue(req);
m_mapBlockRequestEvent.Set();
}
} }
public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags, public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags,
@ -519,12 +553,26 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
/// </summary> /// </summary>
public void process() public void process()
{ {
const int MAX_ASYNC_REQUESTS = 20; const int MAX_ASYNC_REQUESTS = 5;
try try
{ {
while (true) while (true)
{ {
MapRequestState st = requests.Dequeue(1000); MapRequestState st = new MapRequestState();
bool valid = false;
queueEvent.WaitOne();
lock (requests)
{
if (requests.Count > 0)
{
st = requests.Dequeue();
valid = true;
}
if (requests.Count == 0)
queueEvent.Reset();
}
if (!valid)
continue;
// end gracefully // end gracefully
if (st.agentID == STOP_UUID) if (st.agentID == STOP_UUID)
@ -541,14 +589,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle)) if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle))
{ {
while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break // while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
Thread.Sleep(80); // Thread.Sleep(500);
RequestMapItemsDelegate d = RequestMapItemsAsync;
d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null);
//OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
//RequestMapItemsCompleted(response);
Interlocked.Increment(ref nAsyncRequests); Interlocked.Increment(ref nAsyncRequests);
RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
} }
} }
@ -570,110 +615,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
/// <param name="state"></param> /// <param name="state"></param>
public void EnqueueMapItemRequest(MapRequestState state) public void EnqueueMapItemRequest(MapRequestState state)
{ {
requests.Enqueue(state); lock (requests)
}
/// <summary>
/// Sends the mapitem response to the IClientAPI
/// </summary>
/// <param name="response">The OSDMap Response for the mapitem</param>
private void RequestMapItemsCompleted(IAsyncResult iar)
{
AsyncResult result = (AsyncResult)iar;
RequestMapItemsDelegate icon = (RequestMapItemsDelegate)result.AsyncDelegate;
OSDMap response = (OSDMap)icon.EndInvoke(iar);
Interlocked.Decrement(ref nAsyncRequests);
if (!response.ContainsKey("requestID"))
return;
UUID requestID = response["requestID"].AsUUID();
if (requestID != UUID.Zero)
{ {
MapRequestState mrs = new MapRequestState(); queueEvent.Set();
mrs.agentID = UUID.Zero; requests.Enqueue(state);
lock (m_openRequests)
{
if (m_openRequests.ContainsKey(requestID))
{
mrs = m_openRequests[requestID];
m_openRequests.Remove(requestID);
}
}
if (mrs.agentID != UUID.Zero)
{
ScenePresence av = null;
m_scene.TryGetScenePresence(mrs.agentID, out av);
if (av != null)
{
if (response.ContainsKey(mrs.itemtype.ToString()))
{
List<mapItemReply> returnitems = new List<mapItemReply>();
OSDArray itemarray = (OSDArray)response[mrs.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(), mrs.itemtype, mrs.flags);
}
// Service 7 (MAP_ITEM_LAND_FOR_SALE)
uint itemtype = 7;
if (response.ContainsKey(itemtype.ToString()))
{
List<mapItemReply> returnitems = new List<mapItemReply>();
OSDArray itemarray = (OSDArray)response[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, mrs.flags);
}
// Service 1 (MAP_ITEM_TELEHUB)
itemtype = 1;
if (response.ContainsKey(itemtype.ToString()))
{
List<mapItemReply> returnitems = new List<mapItemReply>();
OSDArray itemarray = (OSDArray)response[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, mrs.flags);
}
}
}
} }
} }
@ -700,8 +645,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
EnqueueMapItemRequest(st); EnqueueMapItemRequest(st);
} }
private delegate OSDMap RequestMapItemsDelegate(UUID id, uint flags,
uint EstateID, bool godlike, uint itemtype, ulong regionhandle);
/// <summary> /// <summary>
/// Does the actual remote mapitem request /// Does the actual remote mapitem request
/// This should be called from an asynchronous thread /// This should be called from an asynchronous thread
@ -716,7 +659,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
/// <param name="itemtype">passed in from packet</param> /// <param name="itemtype">passed in from packet</param>
/// <param name="regionhandle">Region we're looking up</param> /// <param name="regionhandle">Region we're looking up</param>
/// <returns></returns> /// <returns></returns>
private OSDMap 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);
@ -739,7 +682,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
} }
if (blacklisted) if (blacklisted)
return new OSDMap(); {
Interlocked.Decrement(ref nAsyncRequests);
return;
}
UUID requestID = UUID.Random(); UUID requestID = UUID.Random();
lock (m_cachedRegionMapItemsAddress) lock (m_cachedRegionMapItemsAddress)
@ -747,6 +693,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle))
httpserver = m_cachedRegionMapItemsAddress[regionhandle]; httpserver = m_cachedRegionMapItemsAddress[regionhandle];
} }
if (httpserver.Length == 0) if (httpserver.Length == 0)
{ {
uint x = 0, y = 0; uint x = 0, y = 0;
@ -791,18 +738,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
// Can't find the http server // Can't find the http server
if (httpserver.Length == 0 || blacklisted) if (httpserver.Length == 0 || blacklisted)
return new OSDMap(); {
Interlocked.Decrement(ref nAsyncRequests);
MapRequestState mrs = new MapRequestState(); return;
mrs.agentID = id; }
mrs.EstateID = EstateID;
mrs.flags = flags;
mrs.godlike = godlike;
mrs.itemtype=itemtype;
mrs.regionhandle = regionhandle;
lock (m_openRequests)
m_openRequests.Add(requestID, mrs);
WebRequest mapitemsrequest = null; WebRequest mapitemsrequest = null;
try try
@ -812,7 +751,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
catch (Exception e) catch (Exception e)
{ {
m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e); m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e);
return new OSDMap(); Interlocked.Decrement(ref nAsyncRequests);
return;
} }
mapitemsrequest.Method = "POST"; mapitemsrequest.Method = "POST";
@ -826,6 +766,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
OSDMap responseMap = new OSDMap(); OSDMap responseMap = new OSDMap();
responseMap["requestID"] = OSD.FromUUID(requestID); responseMap["requestID"] = OSD.FromUUID(requestID);
return;
Stream os = null; Stream os = null;
try try
{ // send the Post { // send the Post
@ -837,7 +778,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
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);
lock (m_blacklistedurls) lock (m_blacklistedurls)
{ {
if (!m_blacklistedurls.ContainsKey(httpserver)) if (!m_blacklistedurls.ContainsKey(httpserver))
@ -846,13 +786,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
return responseMap; Interlocked.Decrement(ref nAsyncRequests);
return;
} }
catch catch
{ {
m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
responseMap["connect"] = OSD.FromBoolean(false); Interlocked.Decrement(ref nAsyncRequests);
return responseMap; return;
} }
finally finally
{ {
@ -873,12 +814,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
} }
else else
{ {
return new OSDMap(); Interlocked.Decrement(ref nAsyncRequests);
return;
} }
} }
catch (WebException) catch (WebException)
{ {
responseMap["connect"] = OSD.FromBoolean(false);
lock (m_blacklistedurls) lock (m_blacklistedurls)
{ {
if (!m_blacklistedurls.ContainsKey(httpserver)) if (!m_blacklistedurls.ContainsKey(httpserver))
@ -887,19 +828,20 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
return responseMap; Interlocked.Decrement(ref nAsyncRequests);
return;
} }
catch catch
{ {
m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
responseMap["connect"] = OSD.FromBoolean(false);
lock (m_blacklistedregions) lock (m_blacklistedregions)
{ {
if (!m_blacklistedregions.ContainsKey(regionhandle)) if (!m_blacklistedregions.ContainsKey(regionhandle))
m_blacklistedregions.Add(regionhandle, Environment.TickCount); m_blacklistedregions.Add(regionhandle, Environment.TickCount);
} }
return responseMap; Interlocked.Decrement(ref nAsyncRequests);
return;
} }
finally finally
{ {
@ -918,14 +860,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
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);
responseMap["connect"] = OSD.FromBoolean(false);
lock (m_blacklistedregions) lock (m_blacklistedregions)
{ {
if (!m_blacklistedregions.ContainsKey(regionhandle)) if (!m_blacklistedregions.ContainsKey(regionhandle))
m_blacklistedregions.Add(regionhandle, Environment.TickCount); m_blacklistedregions.Add(regionhandle, Environment.TickCount);
} }
return responseMap; Interlocked.Decrement(ref nAsyncRequests);
return;
} }
} }
@ -939,7 +881,78 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
} }
} }
return responseMap; Interlocked.Decrement(ref nAsyncRequests);
if (id != UUID.Zero)
{
ScenePresence av = null;
m_scene.TryGetScenePresence(id, out av);
if (av != null)
{
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 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);
}
}
}
} }
/// <summary> /// <summary>
@ -949,7 +962,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
/// <param name="minY"></param> /// <param name="minY"></param>
/// <param name="maxX"></param> /// <param name="maxX"></param>
/// <param name="maxY"></param> /// <param name="maxY"></param>
public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) public void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
{ {
//m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag); //m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag);
if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible
@ -1002,21 +1015,91 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
{ {
MapBlockRequestData req = new MapBlockRequestData();
req.client = remoteClient;
req.minX = minX;
req.maxX = maxX;
req.minY = minY;
req.maxY = maxY;
req.flags = flag;
lock (m_mapBlockRequestEvent)
{
if (!m_mapBlockRequests.ContainsKey(remoteClient.AgentId))
m_mapBlockRequests[remoteClient.AgentId] = new Queue<MapBlockRequestData>();
m_mapBlockRequests[remoteClient.AgentId].Enqueue(req);
m_mapBlockRequestEvent.Set();
}
return new List<MapBlockData>();
}
protected void MapBlockSendThread()
{
while (true)
{
List<MapBlockRequestData> thisRunData = new List<MapBlockRequestData>();
m_mapBlockRequestEvent.WaitOne();
lock (m_mapBlockRequestEvent)
{
int total = 0;
foreach (Queue<MapBlockRequestData> q in m_mapBlockRequests.Values)
{
if (q.Count > 0)
thisRunData.Add(q.Dequeue());
total += q.Count;
}
if (total == 0)
m_mapBlockRequestEvent.Reset();
}
foreach (MapBlockRequestData req in thisRunData)
{
// Null client stops thread
if (req.client == null)
return;
GetAndSendBlocksInternal(req.client, req.minX, req.minY, req.maxX, req.maxY, req.flags);
}
Thread.Sleep(50);
}
}
protected virtual List<MapBlockData> GetAndSendBlocksInternal(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
{
List<MapBlockData> allBlocks = new List<MapBlockData>();
List<MapBlockData> mapBlocks = new List<MapBlockData>(); List<MapBlockData> mapBlocks = new List<MapBlockData>();
List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
(minX - 4) * (int)Constants.RegionSize, minX * (int)Constants.RegionSize,
(maxX + 4) * (int)Constants.RegionSize, maxX * (int)Constants.RegionSize,
(minY - 4) * (int)Constants.RegionSize, minY * (int)Constants.RegionSize,
(maxY + 4) * (int)Constants.RegionSize); maxY * (int)Constants.RegionSize);
// (minX - 4) * (int)Constants.RegionSize,
// (maxX + 4) * (int)Constants.RegionSize,
// (minY - 4) * (int)Constants.RegionSize,
// (maxY + 4) * (int)Constants.RegionSize);
foreach (GridRegion r in regions) foreach (GridRegion r in regions)
{ {
MapBlockData block = new MapBlockData(); MapBlockData block = new MapBlockData();
MapBlockFromGridRegion(block, r, flag); MapBlockFromGridRegion(block, r, flag);
mapBlocks.Add(block); mapBlocks.Add(block);
allBlocks.Add(block);
if (mapBlocks.Count >= 10)
{
remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
mapBlocks.Clear();
Thread.Sleep(50);
}
} }
remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); if (mapBlocks.Count > 0)
remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
return mapBlocks; return allBlocks;
} }
protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag) protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag)
@ -1415,6 +1498,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
{ {
m_rootAgents.Remove(avatar.UUID); m_rootAgents.Remove(avatar.UUID);
} }
lock (m_mapBlockRequestEvent)
{
if (m_mapBlockRequests.ContainsKey(avatar.UUID))
m_mapBlockRequests.Remove(avatar.UUID);
}
} }
public void OnRegionUp(GridRegion otherRegion) public void OnRegionUp(GridRegion otherRegion)
@ -1538,4 +1627,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
public uint itemtype; public uint itemtype;
public ulong regionhandle; public ulong regionhandle;
} }
public struct MapBlockRequestData
{
public IClientAPI client;
public int minX;
public int minY;
public int maxX;
public int maxY;
public uint flags;
}
} }

View File

@ -599,7 +599,20 @@ namespace OpenSim.Region.Framework.Scenes
return v; return v;
} }
public void FromXml2(XmlTextReader _reader, out bool errors) public static SOPVehicle FromXml2(XmlTextReader reader)
{
SOPVehicle vehicle = new SOPVehicle();
bool errors = false;
vehicle.FromXml2(reader, out errors);
if (errors)
return null;
return vehicle;
}
private void FromXml2(XmlTextReader _reader, out bool errors)
{ {
errors = false; errors = false;
reader = _reader; reader = _reader;

View File

@ -623,12 +623,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
private static void ProcessVehicle(SceneObjectPart obj, XmlTextReader reader) private static void ProcessVehicle(SceneObjectPart obj, XmlTextReader reader)
{ {
bool errors = false; SOPVehicle vehicle = SOPVehicle.FromXml2(reader);
SOPVehicle _vehicle = new SOPVehicle();
_vehicle.FromXml2(reader, out errors); if (vehicle == null)
if (errors)
{ {
obj.VehicleParams = null; obj.VehicleParams = null;
m_log.DebugFormat( m_log.DebugFormat(
@ -636,7 +633,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
obj.Name, obj.UUID); obj.Name, obj.UUID);
} }
else else
obj.VehicleParams = _vehicle; {
obj.VehicleParams = vehicle;
}
} }
private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader) private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader)

View File

@ -29,6 +29,7 @@ using System;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Reflection; using System.Reflection;
using System.Threading;
using Nini.Config; using Nini.Config;
using log4net; using log4net;
@ -70,6 +71,8 @@ namespace OpenSim.Server.Handlers.MapImage
class MapServerGetHandler : BaseStreamHandler class MapServerGetHandler : BaseStreamHandler
{ {
public static ManualResetEvent ev = new ManualResetEvent(true);
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IMapImageService m_MapService; private IMapImageService m_MapService;
@ -82,8 +85,13 @@ namespace OpenSim.Server.Handlers.MapImage
public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{ {
byte[] result = new byte[0]; ev.WaitOne();
lock (ev)
{
ev.Reset();
}
byte[] result = new byte[0];
string format = string.Empty; string format = string.Empty;
result = m_MapService.GetMapTile(path.Trim('/'), out format); result = m_MapService.GetMapTile(path.Trim('/'), out format);
if (result.Length > 0) if (result.Length > 0)
@ -100,6 +108,11 @@ namespace OpenSim.Server.Handlers.MapImage
httpResponse.ContentType = "text/plain"; httpResponse.ContentType = "text/plain";
} }
lock (ev)
{
ev.Set();
}
return result; return result;
} }