Merge branch 'avination' into careminster

Conflicts:
	OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
	OpenSim/Region/Framework/Scenes/Scene.cs
avinationmerge
Melanie 2012-09-27 17:29:44 +01:00
commit 001ec0e2e6
36 changed files with 1664 additions and 502 deletions

View File

@ -187,7 +187,11 @@ namespace OpenSim.Capabilities.Handlers
response["headers"] = headers; response["headers"] = headers;
string range = String.Empty; string range = String.Empty;
if (((Hashtable)request["headers"])["Range"] != null)
if (((Hashtable)request["headers"])["range"] != null)
range = (string)((Hashtable)request["headers"])["range"];
else if (((Hashtable)request["headers"])["Range"] != null)
range = (string)((Hashtable)request["headers"])["Range"]; range = (string)((Hashtable)request["headers"])["Range"];
if (!String.IsNullOrEmpty(range)) // JP2's only if (!String.IsNullOrEmpty(range)) // JP2's only
@ -227,17 +231,22 @@ namespace OpenSim.Capabilities.Handlers
// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); // m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
// Always return PartialContent, even if the range covered the entire data length
// We were accidentally sending back 404 before in this situation
// https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
// entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
response["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent;
response["content-type"] = texture.Metadata.ContentType; response["content-type"] = texture.Metadata.ContentType;
headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length);
if (start == 0 && len == texture.Data.Length) // well redudante maybe
byte[] d = new byte[len]; {
Array.Copy(texture.Data, start, d, 0, len); response["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
response["bin_response_data"] = d; response["bin_response_data"] = texture.Data;
}
else
{
response["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent;
headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length);
byte[] d = new byte[len];
Array.Copy(texture.Data, start, d, 0, len);
response["bin_response_data"] = d;
}
// response.Body.Write(texture.Data, start, len); // response.Body.Write(texture.Data, start, len);
} }
} }

View File

@ -30,12 +30,15 @@ using OpenMetaverse;
namespace OpenSim.Framework.Capabilities namespace OpenSim.Framework.Capabilities
{ {
[LLSDType("MAP")] [LLSDType("MAP")]
public class LLSDAssetUploadComplete public class LLSDAssetUploadComplete
{ {
public string new_asset = String.Empty; public string new_asset = String.Empty;
public UUID new_inventory_item = UUID.Zero; public UUID new_inventory_item = UUID.Zero;
// public UUID new_texture_folder_id = UUID.Zero;
public string state = String.Empty; public string state = String.Empty;
public LLSDAssetUploadError error = null;
//public bool success = false; //public bool success = false;
public LLSDAssetUploadComplete() public LLSDAssetUploadComplete()

View File

@ -45,6 +45,10 @@ namespace OpenSim.Framework.Capabilities
public string asset_type = String.Empty; public string asset_type = String.Empty;
public string description = String.Empty; public string description = String.Empty;
public UUID folder_id = UUID.Zero; public UUID folder_id = UUID.Zero;
public UUID texture_folder_id = UUID.Zero;
public int next_owner_mask = 0;
public int group_mask = 0;
public int everyone_mask = 0;
public string inventory_type = String.Empty; public string inventory_type = String.Empty;
public string name = String.Empty; public string name = String.Empty;
public LLSDAssetResource asset_resources = new LLSDAssetResource(); public LLSDAssetResource asset_resources = new LLSDAssetResource();

View File

@ -26,9 +26,17 @@
*/ */
using System; using System;
using OpenMetaverse;
namespace OpenSim.Framework.Capabilities namespace OpenSim.Framework.Capabilities
{ {
[OSDMap]
public class LLSDAssetUploadError
{
public string message = String.Empty;
public UUID identifier = UUID.Zero;
}
[OSDMap] [OSDMap]
public class LLSDAssetUploadResponsePricebrkDown public class LLSDAssetUploadResponsePricebrkDown
{ {
@ -56,11 +64,13 @@ namespace OpenSim.Framework.Capabilities
public string state = String.Empty; public string state = String.Empty;
public int upload_price = 0; public int upload_price = 0;
public LLSDAssetUploadResponseData data = null; public LLSDAssetUploadResponseData data = null;
public LLSDAssetUploadError error = null;
public LLSDAssetUploadResponse() public LLSDAssetUploadResponse()
{ {
} }
} }
[OSDMap] [OSDMap]
public class LLSDNewFileAngentInventoryVariablePriceReplyResponse public class LLSDNewFileAngentInventoryVariablePriceReplyResponse
{ {

View File

@ -150,7 +150,8 @@ namespace OpenSim.Framework
Type == (sbyte)AssetType.SnapshotFolder || Type == (sbyte)AssetType.SnapshotFolder ||
Type == (sbyte)AssetType.TrashFolder || Type == (sbyte)AssetType.TrashFolder ||
Type == (sbyte)AssetType.ImageJPEG || Type == (sbyte)AssetType.ImageJPEG ||
Type == (sbyte) AssetType.ImageTGA || Type == (sbyte)AssetType.ImageTGA ||
Type == (sbyte)AssetType.Mesh ||
Type == (sbyte) AssetType.LSLBytecode); Type == (sbyte) AssetType.LSLBytecode);
} }
} }

View File

@ -425,7 +425,7 @@ namespace OpenSim.Framework.Console
return false; return false;
} }
private Hashtable GetEvents(UUID RequestID, UUID sessionID, string request) private Hashtable GetEvents(UUID RequestID, UUID sessionID)
{ {
ConsoleConnection c = null; ConsoleConnection c = null;

View File

@ -1171,6 +1171,7 @@ namespace OpenSim.Framework
/// </summary> /// </summary>
/// <param name="Item"></param> /// <param name="Item"></param>
void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId); void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId);
void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId);
void SendRemoveInventoryItem(UUID itemID); void SendRemoveInventoryItem(UUID itemID);

View File

@ -45,7 +45,8 @@ namespace OpenSim.Framework
/// <summary> /// <summary>
/// Total number of queues (priorities) available /// Total number of queues (priorities) available
/// </summary> /// </summary>
public const uint NumberOfQueues = 12;
public const uint NumberOfQueues = 12; // includes immediate queues, m_queueCounts need to be set acording
/// <summary> /// <summary>
/// Number of queuest (priorities) that are processed immediately /// Number of queuest (priorities) that are processed immediately
@ -60,7 +61,8 @@ namespace OpenSim.Framework
// each pass. weighted towards the higher priority queues // each pass. weighted towards the higher priority queues
private uint m_nextQueue = 0; private uint m_nextQueue = 0;
private uint m_countFromQueue = 0; private uint m_countFromQueue = 0;
private uint[] m_queueCounts = { 8, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1 }; // first queues are imediate, so no counts
private uint[] m_queueCounts = {0, 0, 8, 4, 4, 2, 2, 2, 2, 1, 1, 1};
// next request is a counter of the number of updates queued, it provides // next request is a counter of the number of updates queued, it provides
// a total ordering on the updates coming through the queue and is more // a total ordering on the updates coming through the queue and is more
@ -137,7 +139,7 @@ namespace OpenSim.Framework
/// </summary> /// </summary>
public bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue) public bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue)
{ {
// If there is anything in priority queue 0, return it first no // If there is anything in imediate queues, return it first no
// matter what else. Breaks fairness. But very useful. // matter what else. Breaks fairness. But very useful.
for (int iq = 0; iq < NumberOfImmediateQueues; iq++) for (int iq = 0; iq < NumberOfImmediateQueues; iq++)
{ {
@ -172,14 +174,13 @@ namespace OpenSim.Framework
} }
// Find the next non-immediate queue with updates in it // Find the next non-immediate queue with updates in it
for (int i = 0; i < NumberOfQueues; ++i) for (uint i = NumberOfImmediateQueues; i < NumberOfQueues; ++i)
{ {
m_nextQueue = (uint)((m_nextQueue + 1) % NumberOfQueues); m_nextQueue++;
m_countFromQueue = m_queueCounts[m_nextQueue]; if(m_nextQueue >= NumberOfQueues)
m_nextQueue = NumberOfImmediateQueues;
// if this is one of the immediate queues, just skip it m_countFromQueue = m_queueCounts[m_nextQueue];
if (m_nextQueue < NumberOfImmediateQueues)
continue;
if (m_heaps[m_nextQueue].Count > 0) if (m_heaps[m_nextQueue].Count > 0)
{ {
@ -189,7 +190,6 @@ namespace OpenSim.Framework
m_lookupTable.Remove(item.Value.Entity.LocalId); m_lookupTable.Remove(item.Value.Entity.LocalId);
timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
value = item.Value; value = item.Value;
return true; return true;
} }
} }

View File

@ -334,6 +334,7 @@ namespace OpenSim.Framework.Servers.HttpServer
StreamReader reader = new StreamReader(requestStream, encoding); StreamReader reader = new StreamReader(requestStream, encoding);
string requestBody = reader.ReadToEnd(); string requestBody = reader.ReadToEnd();
reader.Close();
Hashtable keysvals = new Hashtable(); Hashtable keysvals = new Hashtable();
Hashtable headervals = new Hashtable(); Hashtable headervals = new Hashtable();
@ -648,7 +649,7 @@ namespace OpenSim.Framework.Servers.HttpServer
// Every month or so this will wrap and give bad numbers, not really a problem // Every month or so this will wrap and give bad numbers, not really a problem
// since its just for reporting // since its just for reporting
int tickdiff = requestEndTick - requestStartTick; int tickdiff = requestEndTick - requestStartTick;
if (tickdiff > 3000 && requestHandler.Name != "GetTexture") if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture"))
{ {
m_log.InfoFormat( m_log.InfoFormat(
"[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms", "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms",
@ -1555,6 +1556,8 @@ namespace OpenSim.Framework.Servers.HttpServer
else else
responseString = (string)responsedata["str_response_string"]; responseString = (string)responsedata["str_response_string"];
contentType = (string)responsedata["content_type"]; contentType = (string)responsedata["content_type"];
if (responseString == null)
responseString = String.Empty;
} }
catch catch
{ {

View File

@ -34,7 +34,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public delegate void RequestMethod(UUID requestID, Hashtable request); public delegate void RequestMethod(UUID requestID, Hashtable request);
public delegate bool HasEventsMethod(UUID requestID, UUID pId); public delegate bool HasEventsMethod(UUID requestID, UUID pId);
public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId, string request); public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId);
public delegate Hashtable NoEventsMethod(UUID requestID, UUID pId); public delegate Hashtable NoEventsMethod(UUID requestID, UUID pId);
@ -46,7 +46,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public RequestMethod Request; public RequestMethod Request;
public UUID Id; public UUID Id;
public int TimeOutms; public int TimeOutms;
public EventType Type; public EventType Type;
public enum EventType : int public enum EventType : int
{ {

View File

@ -33,6 +33,7 @@ using log4net;
using HttpServer; using HttpServer;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Monitoring; using OpenSim.Framework.Monitoring;
using Amib.Threading;
/* /*
@ -185,6 +186,8 @@ namespace OpenSim.Framework.Servers.HttpServer
private bool m_running = true; private bool m_running = true;
private int slowCount = 0; private int slowCount = 0;
private SmartThreadPool m_threadPool = new SmartThreadPool(20000, 12, 2);
// private int m_timeout = 1000; // increase timeout 250; now use the event one // private int m_timeout = 1000; // increase timeout 250; now use the event one
public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout) public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout)
@ -202,7 +205,7 @@ namespace OpenSim.Framework.Servers.HttpServer
String.Format("PollServiceWorkerThread{0}", i), String.Format("PollServiceWorkerThread{0}", i),
ThreadPriority.Normal, ThreadPriority.Normal,
false, false,
true, false,
null, null,
int.MaxValue); int.MaxValue);
} }
@ -275,15 +278,7 @@ namespace OpenSim.Framework.Servers.HttpServer
Thread.Sleep(1000); // let the world move Thread.Sleep(1000); // let the world move
foreach (Thread t in m_workerThreads) foreach (Thread t in m_workerThreads)
{ Watchdog.AbortThread(t.ManagedThreadId);
try
{
t.Abort();
}
catch
{
}
}
try try
{ {
@ -326,13 +321,9 @@ namespace OpenSim.Framework.Servers.HttpServer
private void PoolWorkerJob() private void PoolWorkerJob()
{ {
PollServiceHttpRequest req;
StreamReader str;
// while (true)
while (m_running) while (m_running)
{ {
req = m_requests.Dequeue(5000); PollServiceHttpRequest req = m_requests.Dequeue(5000);
Watchdog.UpdateThread(); Watchdog.UpdateThread();
if (req != null) if (req != null)
@ -341,35 +332,41 @@ namespace OpenSim.Framework.Servers.HttpServer
{ {
if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id)) if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
{ {
try Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
{
str = new StreamReader(req.Request.Body); if (responsedata == null)
}
catch (System.ArgumentException)
{
// Stream was not readable means a child agent
// was closed due to logout, leaving the
// Event Queue request orphaned.
continue; continue;
}
try if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.Normal)
{ {
Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id, str.ReadToEnd()); try
DoHTTPGruntWork(m_server, req, responsedata); {
DoHTTPGruntWork(m_server, req, responsedata);
}
catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
{
// Ignore it, no need to reply
}
} }
catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream else
{ {
// Ignore it, no need to reply m_threadPool.QueueWorkItem(x =>
{
try
{
DoHTTPGruntWork(m_server, req, responsedata);
}
catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
{
// Ignore it, no need to reply
}
return null;
}, null);
} }
str.Close();
} }
else else
{ {
// if ((Environment.TickCount - req.RequestTime) > m_timeout)
if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
{ {
DoHTTPGruntWork(m_server, req, DoHTTPGruntWork(m_server, req,

View File

@ -0,0 +1,671 @@
// Proprietary code of Avination Virtual Limited
// (c) 2012 Melanie Thielker, Leal Duarte
//
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Region.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Framework.Capabilities;
using ComponentAce.Compression.Libs.zlib;
using OSDArray = OpenMetaverse.StructuredData.OSDArray;
using OSDMap = OpenMetaverse.StructuredData.OSDMap;
namespace OpenSim.Region.ClientStack.Linden
{
public struct ModelPrimLimits
{
}
public class ModelCost
{
// upload fee defaults
// fees are normalized to 1.0
// this parameters scale them to basic cost ( so 1.0 translates to 10 )
public float ModelMeshCostFactor = 0.0f; // scale total cost relative to basic (excluding textures)
public float ModelTextureCostFactor = 1.0f; // scale textures fee to basic.
public float ModelMinCostFactor = 0.0f; // 0.5f; // minimum total model free excluding textures
// itens costs in normalized values
// ie will be multiplied by basicCost and factors above
public float primCreationCost = 0.002f; // extra cost for each prim creation overhead
// weigthed size to normalized cost
public float bytecost = 1e-5f;
// mesh upload fees based on compressed data sizes
// several data sections are counted more that once
// to promote user optimization
// following parameters control how many extra times they are added
// to global size.
// LOD meshs
const float medSizeWth = 1f; // 2x
const float lowSizeWth = 1.5f; // 2.5x
const float lowestSizeWth = 2f; // 3x
// favor potencially physical optimized meshs versus automatic decomposition
const float physMeshSizeWth = 6f; // counts 7x
const float physHullSizeWth = 8f; // counts 9x
// stream cost area factors
// more or less like SL
const float highLodFactor = 17.36f;
const float midLodFactor = 277.78f;
const float lowLodFactor = 1111.11f;
// physics cost is below, identical to SL, assuming shape type convex
// server cost is below identical to SL assuming non scripted non physical object
// internal
const int bytesPerCoord = 6; // 3 coords, 2 bytes per each
// control prims dimensions
public float PrimScaleMin = 0.001f;
public float NonPhysicalPrimScaleMax = 256f;
public float PhysicalPrimScaleMax = 10f;
public int ObjectLinkedPartsMax = 512;
// storage for a single mesh asset cost parameters
private class ameshCostParam
{
// LOD sizes for size dependent streaming cost
public int highLODSize;
public int medLODSize;
public int lowLODSize;
public int lowestLODSize;
// normalized fee based on compressed data sizes
public float costFee;
// physics cost
public float physicsCost;
}
// calculates a mesh model costs
// returns false on error, with a reason on parameter error
// resources input LLSD request
// basicCost input region assets upload cost
// totalcost returns model total upload fee
// meshcostdata returns detailed costs for viewer
public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost,
LLSDAssetUploadResponseData meshcostdata, out string error, ref string warning)
{
totalcost = 0;
error = string.Empty;
if (resources == null ||
resources.instance_list == null ||
resources.instance_list.Array.Count == 0)
{
error = "missing model information.";
return false;
}
int numberInstances = resources.instance_list.Array.Count;
if( numberInstances > ObjectLinkedPartsMax )
{
error = "Model whould have more than " + ObjectLinkedPartsMax.ToString() + " linked prims";
return false;
}
meshcostdata.model_streaming_cost = 0.0;
meshcostdata.simulation_cost = 0.0;
meshcostdata.physics_cost = 0.0;
meshcostdata.resource_cost = 0.0;
meshcostdata.upload_price_breakdown.mesh_instance = 0;
meshcostdata.upload_price_breakdown.mesh_physics = 0;
meshcostdata.upload_price_breakdown.mesh_streaming = 0;
meshcostdata.upload_price_breakdown.model = 0;
int itmp;
// textures cost
if (resources.texture_list != null && resources.texture_list.Array.Count > 0)
{
float textures_cost = (float)(resources.texture_list.Array.Count * basicCost);
textures_cost *= ModelTextureCostFactor;
itmp = (int)(textures_cost + 0.5f); // round
meshcostdata.upload_price_breakdown.texture = itmp;
totalcost += itmp;
}
// meshs assets cost
float meshsfee = 0;
int numberMeshs = 0;
bool haveMeshs = false;
List<ameshCostParam> meshsCosts = new List<ameshCostParam>();
if (resources.mesh_list != null && resources.mesh_list.Array.Count > 0)
{
numberMeshs = resources.mesh_list.Array.Count;
for (int i = 0; i < numberMeshs; i++)
{
ameshCostParam curCost = new ameshCostParam();
byte[] data = (byte[])resources.mesh_list.Array[i];
if (!MeshCost(data, curCost, out error))
{
return false;
}
meshsCosts.Add(curCost);
meshsfee += curCost.costFee;
}
haveMeshs = true;
}
// instances (prims) cost
int mesh;
int skipedSmall = 0;
for (int i = 0; i < numberInstances; i++)
{
Hashtable inst = (Hashtable)resources.instance_list.Array[i];
ArrayList ascale = (ArrayList)inst["scale"];
Vector3 scale;
double tmp;
tmp = (double)ascale[0];
scale.X = (float)tmp;
tmp = (double)ascale[1];
scale.Y = (float)tmp;
tmp = (double)ascale[2];
scale.Z = (float)tmp;
if (scale.X < PrimScaleMin || scale.Y < PrimScaleMin || scale.Z < PrimScaleMin)
{
skipedSmall++;
continue;
}
if (scale.X > NonPhysicalPrimScaleMax || scale.Y > NonPhysicalPrimScaleMax || scale.Z > NonPhysicalPrimScaleMax)
{
error = "Model contains parts with sides larger than " + NonPhysicalPrimScaleMax.ToString() + "m. Please ajust scale";
return false;
}
if (haveMeshs && inst.ContainsKey("mesh"))
{
mesh = (int)inst["mesh"];
if (mesh >= numberMeshs)
{
error = "Incoerent model information.";
return false;
}
// streamming cost
float sqdiam = scale.LengthSquared();
ameshCostParam curCost = meshsCosts[mesh];
float mesh_streaming = streamingCost(curCost, sqdiam);
meshcostdata.model_streaming_cost += mesh_streaming;
meshcostdata.physics_cost += curCost.physicsCost;
}
else // instance as no mesh ??
{
// to do later if needed
meshcostdata.model_streaming_cost += 0.5f;
meshcostdata.physics_cost += 1.0f;
}
// assume unscripted and static prim server cost
meshcostdata.simulation_cost += 0.5f;
// charge for prims creation
meshsfee += primCreationCost;
}
if (skipedSmall > 0)
{
if (skipedSmall > numberInstances / 2)
{
error = "Model contains too many prims smaller than " + PrimScaleMin.ToString() +
"m minimum allowed size. Please check scalling";
return false;
}
else
warning += skipedSmall.ToString() + " of the requested " +numberInstances.ToString() +
" model prims will not upload because they are smaller than " + PrimScaleMin.ToString() +
"m minimum allowed size. Please check scalling ";
}
if (meshcostdata.physics_cost <= meshcostdata.model_streaming_cost)
meshcostdata.resource_cost = meshcostdata.model_streaming_cost;
else
meshcostdata.resource_cost = meshcostdata.physics_cost;
if (meshcostdata.resource_cost < meshcostdata.simulation_cost)
meshcostdata.resource_cost = meshcostdata.simulation_cost;
// scale cost
// at this point a cost of 1.0 whould mean basic cost
meshsfee *= ModelMeshCostFactor;
if (meshsfee < ModelMinCostFactor)
meshsfee = ModelMinCostFactor;
// actually scale it to basic cost
meshsfee *= (float)basicCost;
meshsfee += 0.5f; // rounding
totalcost += (int)meshsfee;
// breakdown prices
// don't seem to be in use so removed code for now
return true;
}
// single mesh asset cost
private bool MeshCost(byte[] data, ameshCostParam cost, out string error)
{
cost.highLODSize = 0;
cost.medLODSize = 0;
cost.lowLODSize = 0;
cost.lowestLODSize = 0;
cost.physicsCost = 0.0f;
cost.costFee = 0.0f;
error = string.Empty;
if (data == null || data.Length == 0)
{
error = "Missing model information.";
return false;
}
OSD meshOsd = null;
int start = 0;
error = "Invalid model data";
using (MemoryStream ms = new MemoryStream(data))
{
try
{
OSD osd = OSDParser.DeserializeLLSDBinary(ms);
if (osd is OSDMap)
meshOsd = (OSDMap)osd;
else
return false;
}
catch (Exception e)
{
return false;
}
start = (int)ms.Position;
}
OSDMap map = (OSDMap)meshOsd;
OSDMap tmpmap;
int highlod_size = 0;
int medlod_size = 0;
int lowlod_size = 0;
int lowestlod_size = 0;
int skin_size = 0;
int hulls_size = 0;
int phys_nhulls;
int phys_hullsvertices = 0;
int physmesh_size = 0;
int phys_ntriangles = 0;
int submesh_offset = -1;
if (map.ContainsKey("physics_convex"))
{
tmpmap = (OSDMap)map["physics_convex"];
if (tmpmap.ContainsKey("offset"))
submesh_offset = tmpmap["offset"].AsInteger() + start;
if (tmpmap.ContainsKey("size"))
hulls_size = tmpmap["size"].AsInteger();
}
if (submesh_offset < 0 || hulls_size == 0)
{
error = "Missing physics_convex block";
return false;
}
if (!hulls(data, submesh_offset, hulls_size, out phys_hullsvertices, out phys_nhulls))
{
error = "Bad physics_convex block";
return false;
}
submesh_offset = -1;
// only look for LOD meshs sizes
if (map.ContainsKey("high_lod"))
{
tmpmap = (OSDMap)map["high_lod"];
// see at least if there is a offset for this one
if (tmpmap.ContainsKey("offset"))
submesh_offset = tmpmap["offset"].AsInteger() + start;
if (tmpmap.ContainsKey("size"))
highlod_size = tmpmap["size"].AsInteger();
}
if (submesh_offset < 0 || highlod_size <= 0)
{
error = "Missing high_lod block";
return false;
}
bool haveprev = true;
if (map.ContainsKey("medium_lod"))
{
tmpmap = (OSDMap)map["medium_lod"];
if (tmpmap.ContainsKey("size"))
medlod_size = tmpmap["size"].AsInteger();
else
haveprev = false;
}
if (haveprev && map.ContainsKey("low_lod"))
{
tmpmap = (OSDMap)map["low_lod"];
if (tmpmap.ContainsKey("size"))
lowlod_size = tmpmap["size"].AsInteger();
else
haveprev = false;
}
if (haveprev && map.ContainsKey("lowest_lod"))
{
tmpmap = (OSDMap)map["lowest_lod"];
if (tmpmap.ContainsKey("size"))
lowestlod_size = tmpmap["size"].AsInteger();
}
if (map.ContainsKey("skin"))
{
tmpmap = (OSDMap)map["skin"];
if (tmpmap.ContainsKey("size"))
skin_size = tmpmap["size"].AsInteger();
}
cost.highLODSize = highlod_size;
cost.medLODSize = medlod_size;
cost.lowLODSize = lowlod_size;
cost.lowestLODSize = lowestlod_size;
submesh_offset = -1;
tmpmap = null;
if(map.ContainsKey("physics_mesh"))
tmpmap = (OSDMap)map["physics_mesh"];
else if (map.ContainsKey("physics_shape")) // old naming
tmpmap = (OSDMap)map["physics_shape"];
if(tmpmap != null)
{
if (tmpmap.ContainsKey("offset"))
submesh_offset = tmpmap["offset"].AsInteger() + start;
if (tmpmap.ContainsKey("size"))
physmesh_size = tmpmap["size"].AsInteger();
if (submesh_offset >= 0 || physmesh_size > 0)
{
if (!submesh(data, submesh_offset, physmesh_size, out phys_ntriangles))
{
error = "Model data parsing error";
return false;
}
}
}
// upload is done in convex shape type so only one hull
phys_hullsvertices++;
cost.physicsCost = 0.04f * phys_hullsvertices;
float sfee;
sfee = data.Length; // start with total compressed data size
// penalize lod meshs that should be more builder optimized
sfee += medSizeWth * medlod_size;
sfee += lowSizeWth * lowlod_size;
sfee += lowestSizeWth * lowlod_size;
// physics
// favor potencial optimized meshs versus automatic decomposition
if (physmesh_size != 0)
sfee += physMeshSizeWth * (physmesh_size + hulls_size / 4); // reduce cost of mandatory convex hull
else
sfee += physHullSizeWth * hulls_size;
// bytes to money
sfee *= bytecost;
cost.costFee = sfee;
return true;
}
// parses a LOD or physics mesh component
private bool submesh(byte[] data, int offset, int size, out int ntriangles)
{
ntriangles = 0;
OSD decodedMeshOsd = new OSD();
byte[] meshBytes = new byte[size];
System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
try
{
using (MemoryStream inMs = new MemoryStream(meshBytes))
{
using (MemoryStream outMs = new MemoryStream())
{
using (ZOutputStream zOut = new ZOutputStream(outMs))
{
byte[] readBuffer = new byte[4096];
int readLen = 0;
while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
zOut.Write(readBuffer, 0, readLen);
}
zOut.Flush();
outMs.Seek(0, SeekOrigin.Begin);
byte[] decompressedBuf = outMs.GetBuffer();
decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
}
}
}
}
catch (Exception e)
{
return false;
}
OSDArray decodedMeshOsdArray = null;
if ((!decodedMeshOsd is OSDArray))
return false;
byte[] dummy;
decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
foreach (OSD subMeshOsd in decodedMeshOsdArray)
{
if (subMeshOsd is OSDMap)
{
OSDMap subtmpmap = (OSDMap)subMeshOsd;
if (subtmpmap.ContainsKey("NoGeometry") && ((OSDBoolean)subtmpmap["NoGeometry"]))
continue;
if (!subtmpmap.ContainsKey("Position"))
return false;
if (subtmpmap.ContainsKey("TriangleList"))
{
dummy = subtmpmap["TriangleList"].AsBinary();
ntriangles += dummy.Length / bytesPerCoord;
}
else
return false;
}
}
return true;
}
// parses convex hulls component
private bool hulls(byte[] data, int offset, int size, out int nvertices, out int nhulls)
{
nvertices = 0;
nhulls = 1;
OSD decodedMeshOsd = new OSD();
byte[] meshBytes = new byte[size];
System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
try
{
using (MemoryStream inMs = new MemoryStream(meshBytes))
{
using (MemoryStream outMs = new MemoryStream())
{
using (ZOutputStream zOut = new ZOutputStream(outMs))
{
byte[] readBuffer = new byte[4096];
int readLen = 0;
while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
zOut.Write(readBuffer, 0, readLen);
}
zOut.Flush();
outMs.Seek(0, SeekOrigin.Begin);
byte[] decompressedBuf = outMs.GetBuffer();
decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
}
}
}
}
catch (Exception e)
{
return false;
}
OSDMap cmap = (OSDMap)decodedMeshOsd;
if (cmap == null)
return false;
byte[] dummy;
// must have one of this
if (cmap.ContainsKey("BoundingVerts"))
{
dummy = cmap["BoundingVerts"].AsBinary();
nvertices = dummy.Length / bytesPerCoord;
}
else
return false;
/* upload is done with convex shape type
if (cmap.ContainsKey("HullList"))
{
dummy = cmap["HullList"].AsBinary();
nhulls += dummy.Length;
}
if (cmap.ContainsKey("Positions"))
{
dummy = cmap["Positions"].AsBinary();
nvertices = dummy.Length / bytesPerCoord;
}
*/
return true;
}
// returns streaming cost from on mesh LODs sizes in curCost and square of prim size length
private float streamingCost(ameshCostParam curCost, float sqdiam)
{
// compute efective areas
float ma = 262144f;
float mh = sqdiam * highLodFactor;
if (mh > ma)
mh = ma;
float mm = sqdiam * midLodFactor;
if (mm > ma)
mm = ma;
float ml = sqdiam * lowLodFactor;
if (ml > ma)
ml = ma;
float mlst = ma;
mlst -= ml;
ml -= mm;
mm -= mh;
if (mlst < 1.0f)
mlst = 1.0f;
if (ml < 1.0f)
ml = 1.0f;
if (mm < 1.0f)
mm = 1.0f;
if (mh < 1.0f)
mh = 1.0f;
ma = mlst + ml + mm + mh;
// get LODs compressed sizes
// giving 384 bytes bonus
int lst = curCost.lowestLODSize - 384;
int l = curCost.lowLODSize - 384;
int m = curCost.medLODSize - 384;
int h = curCost.highLODSize - 384;
// use previus higher LOD size on missing ones
if (m <= 0)
m = h;
if (l <= 0)
l = m;
if (lst <= 0)
lst = l;
// force minumum sizes
if (lst < 16)
lst = 16;
if (l < 16)
l = 16;
if (m < 16)
m = 16;
if (h < 16)
h = 16;
// compute cost weighted by relative effective areas
float cost = (float)lst * mlst + (float)l * ml + (float)m * mm + (float)h * mh;
cost /= ma;
cost *= 0.004f; // overall tunning parameter
return cost;
}
}
}

View File

@ -419,7 +419,7 @@ namespace OpenSim.Region.ClientStack.Linden
} }
} }
public Hashtable GetEvents(UUID requestID, UUID pAgentId, string request) public Hashtable GetEvents(UUID requestID, UUID pAgentId)
{ {
if (DebugLevel >= 2) if (DebugLevel >= 2)
m_log.DebugFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName); m_log.DebugFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName);

View File

@ -53,6 +53,14 @@ namespace OpenSim.Region.ClientStack.Linden
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")] [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")]
public class GetTextureModule : INonSharedRegionModule public class GetTextureModule : INonSharedRegionModule
{ {
struct aPollRequest
{
public PollServiceTextureEventArgs thepoll;
public UUID reqID;
public Hashtable request;
}
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene; private Scene m_scene;
@ -64,8 +72,8 @@ namespace OpenSim.Region.ClientStack.Linden
private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>(); private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
private static Thread[] m_workerThreads = null; private static Thread[] m_workerThreads = null;
private static OpenMetaverse.BlockingQueue<PollServiceTextureEventArgs> m_queue = private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
new OpenMetaverse.BlockingQueue<PollServiceTextureEventArgs>(); new OpenMetaverse.BlockingQueue<aPollRequest>();
#region ISharedRegionModule Members #region ISharedRegionModule Members
@ -104,7 +112,7 @@ namespace OpenSim.Region.ClientStack.Linden
String.Format("TextureWorkerThread{0}", i), String.Format("TextureWorkerThread{0}", i),
ThreadPriority.Normal, ThreadPriority.Normal,
false, false,
true, false,
null, null,
int.MaxValue); int.MaxValue);
} }
@ -129,7 +137,8 @@ namespace OpenSim.Region.ClientStack.Linden
~GetTextureModule() ~GetTextureModule()
{ {
foreach (Thread t in m_workerThreads) foreach (Thread t in m_workerThreads)
t.Abort(); Watchdog.AbortThread(t.ManagedThreadId);
} }
private class PollServiceTextureEventArgs : PollServiceEventArgs private class PollServiceTextureEventArgs : PollServiceEventArgs
@ -142,40 +151,50 @@ namespace OpenSim.Region.ClientStack.Linden
private Scene m_scene; private Scene m_scene;
public PollServiceTextureEventArgs(UUID pId, Scene scene) : public PollServiceTextureEventArgs(UUID pId, Scene scene) :
base(null, null, null, null, pId, 30000) base(null, null, null, null, pId, int.MaxValue)
{ {
m_scene = scene; m_scene = scene;
HasEvents = (x, y) => { return this.responses.ContainsKey(x); }; HasEvents = (x, y) =>
GetEvents = (x, y, s) =>
{ {
try lock (responses)
return responses.ContainsKey(x);
};
GetEvents = (x, y) =>
{
lock (responses)
{ {
return this.responses[x]; try
} {
finally return responses[x];
{ }
responses.Remove(x); finally
{
responses.Remove(x);
}
} }
}; };
Request = (x, y) => Request = (x, y) =>
{ {
y["RequestID"] = x.ToString(); aPollRequest reqinfo = new aPollRequest();
lock (this.requests) reqinfo.thepoll = this;
this.requests.Add(y); reqinfo.reqID = x;
reqinfo.request = y;
m_queue.Enqueue(this); m_queue.Enqueue(reqinfo);
}; };
// this should never happen except possible on shutdown
NoEvents = (x, y) => NoEvents = (x, y) =>
{ {
lock (this.requests) /*
lock (requests)
{ {
Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString()); Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
requests.Remove(request); requests.Remove(request);
} }
*/
Hashtable response = new Hashtable(); Hashtable response = new Hashtable();
response["int_response_code"] = 500; response["int_response_code"] = 500;
@ -188,25 +207,11 @@ namespace OpenSim.Region.ClientStack.Linden
}; };
} }
public void Process() public void Process(aPollRequest requestinfo)
{ {
Hashtable response; Hashtable response;
Hashtable request = null;
try UUID requestID = requestinfo.reqID;
{
lock (this.requests)
{
request = requests[0];
requests.RemoveAt(0);
}
}
catch
{
return;
}
UUID requestID = new UUID(request["RequestID"].ToString());
// If the avatar is gone, don't bother to get the texture // If the avatar is gone, don't bother to get the texture
if (m_scene.GetScenePresence(Id) == null) if (m_scene.GetScenePresence(Id) == null)
@ -219,13 +224,15 @@ namespace OpenSim.Region.ClientStack.Linden
response["keepalive"] = false; response["keepalive"] = false;
response["reusecontext"] = false; response["reusecontext"] = false;
responses[requestID] = response; lock (responses)
responses[requestID] = response;
return; return;
} }
response = m_getTextureHandler.Handle(request); response = m_getTextureHandler.Handle(requestinfo.request);
lock (responses)
responses[requestID] = response; responses[requestID] = response;
} }
} }
@ -233,8 +240,7 @@ namespace OpenSim.Region.ClientStack.Linden
{ {
string capUrl = "/CAPS/" + UUID.Random() + "/"; string capUrl = "/CAPS/" + UUID.Random() + "/";
// Register this as a poll service // Register this as a poll service
// absurd large timeout to tune later to make a bit less than viewer
PollServiceTextureEventArgs args = new PollServiceTextureEventArgs(agentID, m_scene); PollServiceTextureEventArgs args = new PollServiceTextureEventArgs(agentID, m_scene);
args.Type = PollServiceEventArgs.EventType.Texture; args.Type = PollServiceEventArgs.EventType.Texture;
@ -270,11 +276,10 @@ namespace OpenSim.Region.ClientStack.Linden
{ {
while (true) while (true)
{ {
PollServiceTextureEventArgs args = m_queue.Dequeue(); aPollRequest poolreq = m_queue.Dequeue();
args.Process(); poolreq.thepoll.Process(poolreq);
} }
} }
} }
} }

View File

@ -129,15 +129,15 @@ namespace OpenSim.Region.ClientStack.Linden
// m_log.DebugFormat("[MESH UPLOAD FLAG MODULE]: MeshUploadFlag request"); // m_log.DebugFormat("[MESH UPLOAD FLAG MODULE]: MeshUploadFlag request");
OSDMap data = new OSDMap(); OSDMap data = new OSDMap();
ScenePresence sp = m_scene.GetScenePresence(m_agentID); // ScenePresence sp = m_scene.GetScenePresence(m_agentID);
data["username"] = sp.Firstname + "." + sp.Lastname; // data["username"] = sp.Firstname + "." + sp.Lastname;
data["display_name_next_update"] = new OSDDate(DateTime.Now); // data["display_name_next_update"] = new OSDDate(DateTime.Now);
data["legacy_first_name"] = sp.Firstname; // data["legacy_first_name"] = sp.Firstname;
data["mesh_upload_status"] = "valid"; data["mesh_upload_status"] = "valid";
data["display_name"] = sp.Firstname + " " + sp.Lastname; // data["display_name"] = sp.Firstname + " " + sp.Lastname;
data["legacy_last_name"] = sp.Lastname; // data["legacy_last_name"] = sp.Lastname;
data["id"] = m_agentID; // data["id"] = m_agentID;
data["is_display_name_default"] = true; // data["is_display_name_default"] = true;
//Send back data //Send back data
Hashtable responsedata = new Hashtable(); Hashtable responsedata = new Hashtable();

View File

@ -52,6 +52,13 @@ namespace OpenSim.Region.ClientStack.Linden
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
public class WebFetchInvDescModule : INonSharedRegionModule public class WebFetchInvDescModule : INonSharedRegionModule
{ {
struct aPollRequest
{
public PollServiceInventoryEventArgs thepoll;
public UUID reqID;
public Hashtable request;
}
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene; private Scene m_scene;
@ -64,8 +71,8 @@ namespace OpenSim.Region.ClientStack.Linden
private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>(); private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
private static Thread[] m_workerThreads = null; private static Thread[] m_workerThreads = null;
private static OpenMetaverse.BlockingQueue<PollServiceInventoryEventArgs> m_queue = private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
new OpenMetaverse.BlockingQueue<PollServiceInventoryEventArgs>(); new OpenMetaverse.BlockingQueue<aPollRequest>();
#region ISharedRegionModule Members #region ISharedRegionModule Members
@ -131,49 +138,52 @@ namespace OpenSim.Region.ClientStack.Linden
~WebFetchInvDescModule() ~WebFetchInvDescModule()
{ {
foreach (Thread t in m_workerThreads) foreach (Thread t in m_workerThreads)
t.Abort(); Watchdog.AbortThread(t.ManagedThreadId);
} }
private class PollServiceInventoryEventArgs : PollServiceEventArgs private class PollServiceInventoryEventArgs : PollServiceEventArgs
{ {
private List<Hashtable> requests =
new List<Hashtable>();
private Dictionary<UUID, Hashtable> responses = private Dictionary<UUID, Hashtable> responses =
new Dictionary<UUID, Hashtable>(); new Dictionary<UUID, Hashtable>();
public PollServiceInventoryEventArgs(UUID pId) : public PollServiceInventoryEventArgs(UUID pId) :
base(null, null, null, null, pId, 30000) base(null, null, null, null, pId, int.MaxValue)
{ {
HasEvents = (x, y) => { return this.responses.ContainsKey(x); }; HasEvents = (x, y) => { lock (responses) return responses.ContainsKey(x); };
GetEvents = (x, y, s) => GetEvents = (x, y) =>
{ {
try lock (responses)
{ {
return this.responses[x]; try
} {
finally return responses[x];
{ }
responses.Remove(x); finally
{
responses.Remove(x);
}
} }
}; };
Request = (x, y) => Request = (x, y) =>
{ {
y["RequestID"] = x.ToString(); aPollRequest reqinfo = new aPollRequest();
lock (this.requests) reqinfo.thepoll = this;
this.requests.Add(y); reqinfo.reqID = x;
reqinfo.request = y;
m_queue.Enqueue(this); m_queue.Enqueue(reqinfo);
}; };
NoEvents = (x, y) => NoEvents = (x, y) =>
{ {
lock (this.requests) /*
lock (requests)
{ {
Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString()); Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
requests.Remove(request); requests.Remove(request);
} }
*/
Hashtable response = new Hashtable(); Hashtable response = new Hashtable();
response["int_response_code"] = 500; response["int_response_code"] = 500;
@ -186,24 +196,9 @@ namespace OpenSim.Region.ClientStack.Linden
}; };
} }
public void Process() public void Process(aPollRequest requestinfo)
{ {
Hashtable request = null; UUID requestID = requestinfo.reqID;
try
{
lock (this.requests)
{
request = requests[0];
requests.RemoveAt(0);
}
}
catch
{
return;
}
UUID requestID = new UUID(request["RequestID"].ToString());
Hashtable response = new Hashtable(); Hashtable response = new Hashtable();
@ -212,9 +207,11 @@ namespace OpenSim.Region.ClientStack.Linden
response["keepalive"] = false; response["keepalive"] = false;
response["reusecontext"] = false; response["reusecontext"] = false;
response["str_response_string"] = m_webFetchHandler.FetchInventoryDescendentsRequest(request["body"].ToString(), String.Empty, String.Empty, null, null); response["str_response_string"] = m_webFetchHandler.FetchInventoryDescendentsRequest(
requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null);
responses[requestID] = response; lock (responses)
responses[requestID] = response;
} }
} }
@ -222,8 +219,7 @@ namespace OpenSim.Region.ClientStack.Linden
{ {
string capUrl = "/CAPS/" + UUID.Random() + "/"; string capUrl = "/CAPS/" + UUID.Random() + "/";
// Register this as a poll service // Register this as a poll service
// absurd large timeout to tune later to make a bit less than viewer
PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(agentID); PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(agentID);
args.Type = PollServiceEventArgs.EventType.Inventory; args.Type = PollServiceEventArgs.EventType.Inventory;
@ -259,9 +255,9 @@ namespace OpenSim.Region.ClientStack.Linden
{ {
while (true) while (true)
{ {
PollServiceInventoryEventArgs args = m_queue.Dequeue(); aPollRequest poolreq = m_queue.Dequeue();
args.Process(); poolreq.thepoll.Process(poolreq);
} }
} }
} }

View File

@ -2066,8 +2066,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OutPacket(bulkUpdate, ThrottleOutPacketType.Asset); OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
} }
/// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId) public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
{
SendInventoryItemCreateUpdate(Item, UUID.Zero, callbackId);
}
/// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
{ {
const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
@ -2078,6 +2083,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// TODO: don't create new blocks if recycling an old packet // TODO: don't create new blocks if recycling an old packet
InventoryReply.AgentData.AgentID = AgentId; InventoryReply.AgentData.AgentID = AgentId;
InventoryReply.AgentData.SimApproved = true; InventoryReply.AgentData.SimApproved = true;
InventoryReply.AgentData.TransactionID = transactionID;
InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1]; InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1];
InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock(); InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock();
InventoryReply.InventoryData[0].ItemID = Item.ID; InventoryReply.InventoryData[0].ItemID = Item.ID;

View File

@ -143,7 +143,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
} }
} }
public void RequestCreateInventoryItem(IClientAPI remoteClient, public bool RequestCreateInventoryItem(IClientAPI remoteClient,
UUID transactionID, UUID folderID, uint callbackID, UUID transactionID, UUID folderID, uint callbackID,
string description, string name, sbyte invType, string description, string name, sbyte invType,
sbyte type, byte wearableType, uint nextOwnerMask) sbyte type, byte wearableType, uint nextOwnerMask)
@ -153,6 +153,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
uploader.RequestCreateInventoryItem( uploader.RequestCreateInventoryItem(
remoteClient, folderID, callbackID, remoteClient, folderID, callbackID,
description, name, invType, type, wearableType, nextOwnerMask); description, name, invType, type, wearableType, nextOwnerMask);
return true;
} }
public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient,
@ -172,4 +174,4 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
uploader.RequestUpdateInventoryItem(remoteClient, item); uploader.RequestUpdateInventoryItem(remoteClient, item);
} }
} }
} }

View File

@ -158,7 +158,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
/// <param name="type"></param> /// <param name="type"></param>
/// <param name="wearableType"></param> /// <param name="wearableType"></param>
/// <param name="nextOwnerMask"></param> /// <param name="nextOwnerMask"></param>
public void HandleItemCreationFromTransaction(IClientAPI remoteClient, public bool HandleItemCreationFromTransaction(IClientAPI remoteClient,
UUID transactionID, UUID folderID, uint callbackID, UUID transactionID, UUID folderID, uint callbackID,
string description, string name, sbyte invType, string description, string name, sbyte invType,
sbyte type, byte wearableType, uint nextOwnerMask) sbyte type, byte wearableType, uint nextOwnerMask)
@ -169,7 +169,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
AgentAssetTransactions transactions = AgentAssetTransactions transactions =
GetUserTransactions(remoteClient.AgentId); GetUserTransactions(remoteClient.AgentId);
transactions.RequestCreateInventoryItem(remoteClient, transactionID, return transactions.RequestCreateInventoryItem(remoteClient, transactionID,
folderID, callbackID, description, name, invType, type, folderID, callbackID, description, name, invType, type,
wearableType, nextOwnerMask); wearableType, nextOwnerMask);
} }

View File

@ -256,7 +256,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
if (sp.IsChildAgent) if (sp.IsChildAgent)
return; return;
sp.ControllingClient.Kick(reason); sp.ControllingClient.Kick(reason);
sp.Scene.IncomingCloseAgent(sp.UUID); sp.MakeChildAgent();
sp.ControllingClient.Close();
} }
private void OnIncomingInstantMessage(GridInstantMessage msg) private void OnIncomingInstantMessage(GridInstantMessage msg)

View File

@ -663,7 +663,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// //
// This sleep can be increased if necessary. However, whilst it's active, // This sleep can be increased if necessary. However, whilst it's active,
// an agent cannot teleport back to this region if it has teleported away. // an agent cannot teleport back to this region if it has teleported away.
Thread.Sleep(2000); Thread.Sleep(3000);
sp.Scene.IncomingCloseAgent(sp.UUID, false); sp.Scene.IncomingCloseAgent(sp.UUID, false);
} }

View File

@ -186,45 +186,44 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
if (folder == null || folder.Owner != remoteClient.AgentId) if (folder == null || folder.Owner != remoteClient.AgentId)
return; return;
if (transactionID == UUID.Zero) if (transactionID != UUID.Zero)
{
ScenePresence presence;
if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence))
{
byte[] data = null;
if (invType == (sbyte)InventoryType.Landmark && presence != null)
{
string suffix = string.Empty, prefix = string.Empty;
string strdata = GenerateLandmark(presence, out prefix, out suffix);
data = Encoding.ASCII.GetBytes(strdata);
name = prefix + name;
description += suffix;
}
AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId);
m_Scene.AssetService.Store(asset);
m_Scene.CreateNewInventoryItem(
remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
name, description, 0, callbackID, asset, invType, nextOwnerMask, creationDate);
}
else
{
m_log.ErrorFormat(
"[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem",
remoteClient.AgentId);
}
}
else
{ {
IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule; IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule;
if (agentTransactions != null) if (agentTransactions != null)
{ {
agentTransactions.HandleItemCreationFromTransaction( if (agentTransactions.HandleItemCreationFromTransaction(
remoteClient, transactionID, folderID, callbackID, description, remoteClient, transactionID, folderID, callbackID, description,
name, invType, assetType, wearableType, nextOwnerMask); name, invType, assetType, wearableType, nextOwnerMask))
return;
} }
} }
ScenePresence presence;
if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence))
{
byte[] data = null;
if (invType == (sbyte)InventoryType.Landmark && presence != null)
{
string suffix = string.Empty, prefix = string.Empty;
string strdata = GenerateLandmark(presence, out prefix, out suffix);
data = Encoding.ASCII.GetBytes(strdata);
name = prefix + name;
description += suffix;
}
AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId);
m_Scene.AssetService.Store(asset);
m_Scene.CreateNewInventoryItem(
remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
name, description, 0, callbackID, asset, invType, nextOwnerMask, creationDate,transactionID);
}
else
{
m_log.ErrorFormat(
"[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem",
remoteClient.AgentId);
}
} }
protected virtual string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix) protected virtual string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix)

View File

@ -461,7 +461,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
} }
} }
} }
private Hashtable GetEvents(UUID requestID, UUID sessionID, string request) private Hashtable GetEvents(UUID requestID, UUID sessionID)
{ {
UrlData url = null; UrlData url = null;
RequestData requestData = null; RequestData requestData = null;

View File

@ -36,7 +36,7 @@ namespace OpenSim.Region.Framework.Interfaces
void HandleItemUpdateFromTransaction(IClientAPI remoteClient, UUID transactionID, void HandleItemUpdateFromTransaction(IClientAPI remoteClient, UUID transactionID,
InventoryItemBase item); InventoryItemBase item);
void HandleItemCreationFromTransaction(IClientAPI remoteClient, UUID transactionID, UUID folderID, bool HandleItemCreationFromTransaction(IClientAPI remoteClient, UUID transactionID, UUID folderID,
uint callbackID, string description, string name, sbyte invType, uint callbackID, string description, string name, sbyte invType,
sbyte type, byte wearableType, uint nextOwnerMask); sbyte type, byte wearableType, uint nextOwnerMask);

View File

@ -904,11 +904,22 @@ namespace OpenSim.Region.Framework.Scenes
public void CreateNewInventoryItem( public void CreateNewInventoryItem(
IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
string name, string description, uint flags, uint callbackID, string name, string description, uint flags, uint callbackID,
AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate) AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate, UUID transationID)
{ {
CreateNewInventoryItem( CreateNewInventoryItem(
remoteClient, creatorID, creatorData, folderID, name, description, flags, callbackID, asset, invType, remoteClient, creatorID, creatorData, folderID, name, description, flags, callbackID, asset, invType,
(uint)PermissionMask.All, (uint)PermissionMask.All, 0, nextOwnerMask, 0, creationDate); (uint)PermissionMask.All, (uint)PermissionMask.All, 0, nextOwnerMask, 0, creationDate, transationID);
}
private void CreateNewInventoryItem(
IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
string name, string description, uint flags, uint callbackID, AssetBase asset, sbyte invType,
uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate)
{
CreateNewInventoryItem(remoteClient, creatorID, creatorData, folderID,
name, description, flags, callbackID, asset, invType,
baseMask, currentMask, everyoneMask, nextOwnerMask, groupMask, creationDate, UUID.Zero);
} }
/// <summary> /// <summary>
@ -933,7 +944,7 @@ namespace OpenSim.Region.Framework.Scenes
private void CreateNewInventoryItem( private void CreateNewInventoryItem(
IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
string name, string description, uint flags, uint callbackID, AssetBase asset, sbyte invType, string name, string description, uint flags, uint callbackID, AssetBase asset, sbyte invType,
uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate) uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate,UUID transationID)
{ {
InventoryItemBase item = new InventoryItemBase(); InventoryItemBase item = new InventoryItemBase();
item.Owner = remoteClient.AgentId; item.Owner = remoteClient.AgentId;
@ -956,7 +967,7 @@ namespace OpenSim.Region.Framework.Scenes
if (AddInventoryItem(item)) if (AddInventoryItem(item))
{ {
remoteClient.SendInventoryItemCreateUpdate(item, callbackID); remoteClient.SendInventoryItemCreateUpdate(item, transationID, callbackID);
} }
else else
{ {

View File

@ -4372,7 +4372,7 @@ namespace OpenSim.Region.Framework.Scenes
ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); ScenePresence presence = m_sceneGraph.GetScenePresence(agentID);
if (presence != null) if (presence != null)
{ {
presence.ControllingClient.Close(true, force); presence.ControllingClient.Close(force, force);
return true; return true;
} }

View File

@ -2146,10 +2146,10 @@ namespace OpenSim.Region.Framework.Scenes
{ {
if (asset != null) if (asset != null)
SculptTextureCallback(asset); SculptTextureCallback(asset);
else // else
m_log.WarnFormat( // m_log.WarnFormat(
"[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data", // "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
Name, UUID, id); // Name, UUID, id);
} }
/// <summary> /// <summary>

View File

@ -1100,7 +1100,12 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId) public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
{ {
}
public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
{
} }
public void SendRemoveInventoryItem(UUID itemID) public void SendRemoveInventoryItem(UUID itemID)

View File

@ -739,6 +739,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{ {
} }
public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
{
}
public virtual void SendRemoveInventoryItem(UUID itemID) public virtual void SendRemoveInventoryItem(UUID itemID)
{ {
} }

View File

@ -902,7 +902,7 @@ namespace OpenSim.Region.Physics.OdePlugin
axis.X = (axis.X > 0) ? 1f : 0f; axis.X = (axis.X > 0) ? 1f : 0f;
axis.Y = (axis.Y > 0) ? 1f : 0f; axis.Y = (axis.Y > 0) ? 1f : 0f;
axis.Z = (axis.Z > 0) ? 1f : 0f; axis.Z = (axis.Z > 0) ? 1f : 0f;
m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z); // m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
AddChange(changes.AngLock, axis); AddChange(changes.AngLock, axis);
} }
else else

View File

@ -10149,31 +10149,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
UUID key = new UUID(); UUID key = new UUID();
if (UUID.TryParse(id, out key)) if (UUID.TryParse(id, out key))
{ {
try // return total object mass
{ SceneObjectPart part = World.GetSceneObjectPart(key);
/* if (part != null)
SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); return part.ParentGroup.GetMass();
if (obj != null)
return (double)obj.GetMass();
*/
// return total object mass
SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
if (obj != null)
return obj.GetMass();
// the object is null so the key is for an avatar // the object is null so the key is for an avatar
ScenePresence avatar = World.GetScenePresence(key); ScenePresence avatar = World.GetScenePresence(key);
if (avatar != null) if (avatar != null)
if (avatar.IsChildAgent)
// reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
// child agents have a mass of 1.0
return 1;
else
return (double)avatar.GetMass();
}
catch (KeyNotFoundException)
{ {
return 0; // The Object/Agent not in the region so just return zero if (avatar.IsChildAgent)
{
// reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
// child agents have a mass of 1.0
return 1;
}
else
{
return (double)avatar.GetMass();
}
} }
} }
return 0; return 0;

View File

@ -443,7 +443,15 @@ namespace OpenSim.Server.Handlers.Simulation
// subclasses can override this // subclasses can override this
protected virtual bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) protected virtual bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason)
{ {
return m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason); reason = String.Empty;
Util.FireAndForget(x =>
{
string r;
m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out r);
});
return true;
} }
} }

View File

@ -27,6 +27,7 @@
using log4net; using log4net;
using System; using System;
using System.Threading;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
@ -50,7 +51,7 @@ namespace OpenSim.Services.Connectors
private IImprovedAssetCache m_Cache = null; private IImprovedAssetCache m_Cache = null;
private int m_retryCounter; private int m_retryCounter;
private Dictionary<int, List<AssetBase>> m_retryQueue = new Dictionary<int, List<AssetBase>>(); private Dictionary<int, List<AssetBase>> m_retryQueue = new Dictionary<int, List<AssetBase>>();
private Timer m_retryTimer; private System.Timers.Timer m_retryTimer;
private delegate void AssetRetrievedEx(AssetBase asset); private delegate void AssetRetrievedEx(AssetBase asset);
// Keeps track of concurrent requests for the same asset, so that it's only loaded once. // Keeps track of concurrent requests for the same asset, so that it's only loaded once.
@ -61,6 +62,8 @@ namespace OpenSim.Services.Connectors
private Dictionary<string, string> m_UriMap = new Dictionary<string, string>(); private Dictionary<string, string> m_UriMap = new Dictionary<string, string>();
private Thread[] m_fetchThreads;
public AssetServicesConnector() public AssetServicesConnector()
{ {
} }
@ -96,7 +99,7 @@ namespace OpenSim.Services.Connectors
} }
m_retryTimer = new Timer(); m_retryTimer = new System.Timers.Timer();
m_retryTimer.Elapsed += new ElapsedEventHandler(retryCheck); m_retryTimer.Elapsed += new ElapsedEventHandler(retryCheck);
m_retryTimer.Interval = 60000; m_retryTimer.Interval = 60000;
@ -112,6 +115,14 @@ namespace OpenSim.Services.Connectors
m_UriMap[prefix] = groupHost; m_UriMap[prefix] = groupHost;
//m_log.DebugFormat("[ASSET]: Using {0} for prefix {1}", groupHost, prefix); //m_log.DebugFormat("[ASSET]: Using {0} for prefix {1}", groupHost, prefix);
} }
m_fetchThreads = new Thread[2];
for (int i = 0 ; i < 2 ; i++)
{
m_fetchThreads[i] = new Thread(AssetRequestProcessor);
m_fetchThreads[i].Start();
}
} }
private string MapServer(string id) private string MapServer(string id)
@ -261,6 +272,66 @@ namespace OpenSim.Services.Connectors
return null; return null;
} }
private class QueuedAssetRequest
{
public string uri;
public string id;
}
private OpenMetaverse.BlockingQueue<QueuedAssetRequest> m_requestQueue =
new OpenMetaverse.BlockingQueue<QueuedAssetRequest>();
private void AssetRequestProcessor()
{
QueuedAssetRequest r;
while (true)
{
r = m_requestQueue.Dequeue();
string uri = r.uri;
string id = r.id;
bool success = false;
try
{
AsynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0,
delegate(AssetBase a)
{
if (m_Cache != null)
m_Cache.Cache(a);
List<AssetRetrievedEx> handlers;
lock (m_AssetHandlers)
{
handlers = m_AssetHandlers[id];
m_AssetHandlers.Remove(id);
}
foreach (AssetRetrievedEx h in handlers)
h.Invoke(a);
if (handlers != null)
handlers.Clear();
}, 30);
success = true;
}
finally
{
if (!success)
{
List<AssetRetrievedEx> handlers;
lock (m_AssetHandlers)
{
handlers = m_AssetHandlers[id];
m_AssetHandlers.Remove(id);
}
if (handlers != null)
handlers.Clear();
}
}
}
}
public bool Get(string id, Object sender, AssetRetrieved handler) public bool Get(string id, Object sender, AssetRetrieved handler)
{ {
string uri = MapServer(id) + "/assets/" + id; string uri = MapServer(id) + "/assets/" + id;
@ -293,52 +364,11 @@ namespace OpenSim.Services.Connectors
m_AssetHandlers.Add(id, handlers); m_AssetHandlers.Add(id, handlers);
} }
bool success = false; QueuedAssetRequest request = new QueuedAssetRequest();
try request.id = id;
{ request.uri = uri;
AsynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0,
delegate(AssetBase a)
{
if (m_Cache != null)
m_Cache.Cache(a);
/*
AssetRetrievedEx handlers;
lock (m_AssetHandlers)
{
handlers = m_AssetHandlers[id];
m_AssetHandlers.Remove(id);
}
handlers.Invoke(a); m_requestQueue.Enqueue(request);
*/
List<AssetRetrievedEx> handlers;
lock (m_AssetHandlers)
{
handlers = m_AssetHandlers[id];
m_AssetHandlers.Remove(id);
}
foreach (AssetRetrievedEx h in handlers)
h.Invoke(a);
if (handlers != null)
handlers.Clear();
}, 30);
success = true;
}
finally
{
if (!success)
{
List<AssetRetrievedEx> handlers;
lock (m_AssetHandlers)
{
handlers = m_AssetHandlers[id];
m_AssetHandlers.Remove(id);
}
if (handlers != null)
handlers.Clear();
}
}
} }
else else
{ {

View File

@ -716,6 +716,10 @@ namespace OpenSim.Tests.Common.Mock
{ {
} }
public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
{
}
public virtual void SendRemoveInventoryItem(UUID itemID) public virtual void SendRemoveInventoryItem(UUID itemID)
{ {
} }

View File

@ -162,6 +162,7 @@
<Reference name="XMLRPC" path="../../../../bin/"/> <Reference name="XMLRPC" path="../../../../bin/"/>
<Reference name="log4net" path="../../../../bin/"/> <Reference name="log4net" path="../../../../bin/"/>
<Reference name="HttpServer_OpenSim" path="../../../../bin/"/> <Reference name="HttpServer_OpenSim" path="../../../../bin/"/>
<Reference name="SmartThreadPool"/>
<Files> <Files>
<Match pattern="*.cs" recurse="true"> <Match pattern="*.cs" recurse="true">
@ -1703,7 +1704,7 @@
<Reference name="OpenSim.Capabilities"/> <Reference name="OpenSim.Capabilities"/>
<Reference name="OpenSim.Capabilities.Handlers"/> <Reference name="OpenSim.Capabilities.Handlers"/>
<Reference name="OpenSim.Framework"/> <Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.Monitoring"/> <Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Framework.Servers"/> <Reference name="OpenSim.Framework.Servers"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/> <Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Framework.Console"/> <Reference name="OpenSim.Framework.Console"/>
@ -1713,6 +1714,7 @@
<Reference name="Nini" path="../../../../../bin/"/> <Reference name="Nini" path="../../../../../bin/"/>
<Reference name="log4net" path="../../../../../bin/"/> <Reference name="log4net" path="../../../../../bin/"/>
<Reference name="Nini" path="../../../../../bin/"/> <Reference name="Nini" path="../../../../../bin/"/>
<Reference name="zlib.net" path="../../../../../bin/"/>
<Files> <Files>
<Match pattern="*.cs" recurse="true"> <Match pattern="*.cs" recurse="true">