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;
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"];
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);
// 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;
if (start == 0 && len == texture.Data.Length) // well redudante maybe
{
response["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
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);
}
}

View File

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

View File

@ -45,6 +45,10 @@ namespace OpenSim.Framework.Capabilities
public string asset_type = String.Empty;
public string description = String.Empty;
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 name = String.Empty;
public LLSDAssetResource asset_resources = new LLSDAssetResource();

View File

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

View File

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

View File

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

View File

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

View File

@ -45,7 +45,8 @@ namespace OpenSim.Framework
/// <summary>
/// Total number of queues (priorities) available
/// </summary>
public const uint NumberOfQueues = 12;
public const uint NumberOfQueues = 12; // includes immediate queues, m_queueCounts need to be set acording
/// <summary>
/// Number of queuest (priorities) that are processed immediately
@ -60,7 +61,8 @@ namespace OpenSim.Framework
// each pass. weighted towards the higher priority queues
private uint m_nextQueue = 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
// a total ordering on the updates coming through the queue and is more
@ -137,7 +139,7 @@ namespace OpenSim.Framework
/// </summary>
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.
for (int iq = 0; iq < NumberOfImmediateQueues; iq++)
{
@ -172,14 +174,13 @@ namespace OpenSim.Framework
}
// 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_countFromQueue = m_queueCounts[m_nextQueue];
m_nextQueue++;
if(m_nextQueue >= NumberOfQueues)
m_nextQueue = NumberOfImmediateQueues;
// if this is one of the immediate queues, just skip it
if (m_nextQueue < NumberOfImmediateQueues)
continue;
m_countFromQueue = m_queueCounts[m_nextQueue];
if (m_heaps[m_nextQueue].Count > 0)
{
@ -189,7 +190,6 @@ namespace OpenSim.Framework
m_lookupTable.Remove(item.Value.Entity.LocalId);
timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
value = item.Value;
return true;
}
}

View File

@ -334,6 +334,7 @@ namespace OpenSim.Framework.Servers.HttpServer
StreamReader reader = new StreamReader(requestStream, encoding);
string requestBody = reader.ReadToEnd();
reader.Close();
Hashtable keysvals = 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
// since its just for reporting
int tickdiff = requestEndTick - requestStartTick;
if (tickdiff > 3000 && requestHandler.Name != "GetTexture")
if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture"))
{
m_log.InfoFormat(
"[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
responseString = (string)responsedata["str_response_string"];
contentType = (string)responsedata["content_type"];
if (responseString == null)
responseString = String.Empty;
}
catch
{

View File

@ -34,7 +34,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public delegate void RequestMethod(UUID requestID, Hashtable request);
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);

View File

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

View File

@ -55,7 +55,9 @@ namespace OpenSim.Region.ClientStack.Linden
{
public delegate void UpLoadedAsset(
string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder,
byte[] data, string inventoryType, string assetType);
byte[] data, string inventoryType, string assetType,
int cost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
bool IsAtestUpload, ref string error);
public delegate UUID UpdateItem(UUID itemID, byte[] data);
@ -87,6 +89,7 @@ namespace OpenSim.Region.ClientStack.Linden
private Scene m_Scene;
private Caps m_HostCapsObj;
private ModelCost m_ModelCost;
private static readonly string m_requestPath = "0000/";
// private static readonly string m_mapLayerPath = "0001/";
@ -115,12 +118,50 @@ namespace OpenSim.Region.ClientStack.Linden
private IAssetService m_assetService;
private bool m_dumpAssetsToFile = false;
private string m_regionName;
private int m_levelUpload = 0;
private bool m_enableFreeTestUpload = false; // allows "TEST-" prefix hack
private bool m_ForceFreeTestUpload = false; // forces all uploads to be test
private bool m_enableModelUploadTextureToInventory = false; // place uploaded textures also in inventory
// may not be visible till relog
private bool m_RestrictFreeTestUploadPerms = false; // reduces also the permitions. Needs a creator defined!!
private UUID m_testAssetsCreatorID = UUID.Zero;
private float m_PrimScaleMin = 0.001f;
private enum FileAgentInventoryState : int
{
idle = 0,
processRequest = 1,
waitUpload = 2,
processUpload = 3
}
private FileAgentInventoryState m_FileAgentInventoryState = FileAgentInventoryState.idle;
public BunchOfCaps(Scene scene, Caps caps)
{
m_Scene = scene;
m_HostCapsObj = caps;
// create a model upload cost provider
m_ModelCost = new ModelCost();
// tell it about scene object limits
m_ModelCost.NonPhysicalPrimScaleMax = m_Scene.m_maxNonphys;
m_ModelCost.PhysicalPrimScaleMax = m_Scene.m_maxPhys;
// m_ModelCost.ObjectLinkedPartsMax = ??
// m_ModelCost.PrimScaleMin = ??
m_PrimScaleMin = m_ModelCost.PrimScaleMin;
float modelTextureUploadFactor = m_ModelCost.ModelTextureCostFactor;
float modelUploadFactor = m_ModelCost.ModelMeshCostFactor;
float modelMinUploadCostFactor = m_ModelCost.ModelMinCostFactor;
float modelPrimCreationCost = m_ModelCost.primCreationCost;
float modelMeshByteCost = m_ModelCost.bytecost;
IConfigSource config = m_Scene.Config;
if (config != null)
{
@ -135,6 +176,37 @@ namespace OpenSim.Region.ClientStack.Linden
{
m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
}
// economy for model upload
IConfig EconomyConfig = config.Configs["Economy"];
if (EconomyConfig != null)
{
modelUploadFactor = EconomyConfig.GetFloat("MeshModelUploadCostFactor", modelUploadFactor);
modelTextureUploadFactor = EconomyConfig.GetFloat("MeshModelUploadTextureCostFactor", modelTextureUploadFactor);
modelMinUploadCostFactor = EconomyConfig.GetFloat("MeshModelMinCostFactor", modelMinUploadCostFactor);
// next 2 are normalized so final cost is afected by modelUploadFactor above and normal cost
modelPrimCreationCost = EconomyConfig.GetFloat("ModelPrimCreationCost", modelPrimCreationCost);
modelMeshByteCost = EconomyConfig.GetFloat("ModelMeshByteCost", modelMeshByteCost);
m_enableModelUploadTextureToInventory = EconomyConfig.GetBoolean("MeshModelAllowTextureToInventory", m_enableModelUploadTextureToInventory);
m_RestrictFreeTestUploadPerms = EconomyConfig.GetBoolean("m_RestrictFreeTestUploadPerms", m_RestrictFreeTestUploadPerms);
m_enableFreeTestUpload = EconomyConfig.GetBoolean("AllowFreeTestUpload", m_enableFreeTestUpload);
m_ForceFreeTestUpload = EconomyConfig.GetBoolean("ForceFreeTestUpload", m_ForceFreeTestUpload);
string testcreator = EconomyConfig.GetString("TestAssetsCreatorID", "");
if (testcreator != "")
{
UUID id;
UUID.TryParse(testcreator, out id);
if (id != null)
m_testAssetsCreatorID = id;
}
m_ModelCost.ModelMeshCostFactor = modelUploadFactor;
m_ModelCost.ModelTextureCostFactor = modelTextureUploadFactor;
m_ModelCost.ModelMinCostFactor = modelMinUploadCostFactor;
m_ModelCost.primCreationCost = modelPrimCreationCost;
m_ModelCost.bytecost = modelMeshByteCost;
}
}
m_assetService = m_Scene.AssetService;
@ -146,6 +218,8 @@ namespace OpenSim.Region.ClientStack.Linden
ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset;
TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset;
GetClient = m_Scene.SceneGraph.GetControllingClient;
m_FileAgentInventoryState = FileAgentInventoryState.idle;
}
/// <summary>
@ -191,7 +265,6 @@ namespace OpenSim.Region.ClientStack.Linden
{
try
{
// I don't think this one works...
m_HostCapsObj.RegisterHandler(
"NewFileAgentInventory",
new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>(
@ -215,8 +288,6 @@ namespace OpenSim.Region.ClientStack.Linden
IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected);
m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler);
m_HostCapsObj.RegisterHandler(
"CopyInventoryFromNotecard",
new RestStreamHandler(
@ -387,37 +458,6 @@ namespace OpenSim.Region.ClientStack.Linden
return UUID.Zero;
}
private delegate void UploadWithCostCompleteDelegate(string assetName,
string assetDescription, UUID assetID, UUID inventoryItem,
UUID parentFolder, byte[] data, string inventoryType,
string assetType, uint cost);
private class AssetUploaderWithCost : AssetUploader
{
private uint m_cost;
public event UploadWithCostCompleteDelegate OnUpLoad;
public AssetUploaderWithCost(string assetName, string description, UUID assetID,
UUID inventoryItem, UUID parentFolderID, string invType, string assetType,
string path, IHttpServer httpServer, bool dumpAssetsToFile, uint cost) :
base(assetName, description, assetID, inventoryItem, parentFolderID,
invType, assetType, path, httpServer, dumpAssetsToFile)
{
m_cost = cost;
base.OnUpLoad += UploadCompleteHandler;
}
private void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
string assetType)
{
OnUpLoad(assetName, assetDescription, assetID, inventoryItem, parentFolder,
data, inventoryType, assetType, m_cost);
}
}
/// <summary>
///
/// </summary>
@ -428,7 +468,47 @@ namespace OpenSim.Region.ClientStack.Linden
//m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString());
//m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type);
uint cost = 0;
// start by getting the client
IClientAPI client = null;
m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
// check current state so we only have one service at a time
lock (m_ModelCost)
{
switch (m_FileAgentInventoryState)
{
case FileAgentInventoryState.processRequest:
case FileAgentInventoryState.processUpload:
LLSDAssetUploadError resperror = new LLSDAssetUploadError();
resperror.message = "Uploader busy processing previus request";
resperror.identifier = UUID.Zero;
LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
errorResponse.uploader = "";
errorResponse.state = "error";
errorResponse.error = resperror;
return errorResponse;
break;
case FileAgentInventoryState.waitUpload:
// todo stop current uploader server
break;
case FileAgentInventoryState.idle:
default:
break;
}
m_FileAgentInventoryState = FileAgentInventoryState.processRequest;
}
int cost = 0;
int nreqtextures = 0;
int nreqmeshs= 0;
int nreqinstances = 0;
bool IsAtestUpload = false;
string assetName = llsdRequest.name;
LLSDAssetUploadResponseData meshcostdata = new LLSDAssetUploadResponseData();
if (llsdRequest.asset_type == "texture" ||
llsdRequest.asset_type == "animation" ||
@ -436,83 +516,128 @@ namespace OpenSim.Region.ClientStack.Linden
llsdRequest.asset_type == "sound")
{
ScenePresence avatar = null;
IClientAPI client = null;
m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar);
// check user level
if (avatar != null)
{
client = avatar.ControllingClient;
if (avatar.UserLevel < m_levelUpload)
{
if (client != null)
client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false);
LLSDAssetUploadError resperror = new LLSDAssetUploadError();
resperror.message = "Insufficient permissions to upload";
resperror.identifier = UUID.Zero;
LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
errorResponse.uploader = "";
errorResponse.state = "error";
errorResponse.error = resperror;
lock (m_ModelCost)
m_FileAgentInventoryState = FileAgentInventoryState.idle;
return errorResponse;
}
}
// check funds
// check test upload and funds
if (client != null)
{
IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
int baseCost = 0;
if (mm != null)
{
// XPTO: The cost should be calculated about here
baseCost = mm.UploadCharge;
string warning = String.Empty;
if (llsdRequest.asset_type == "mesh")
{
cost += 20; // Constant for now to test showing a price
string error;
int modelcost;
if (llsdRequest.asset_resources == null)
if (!m_ModelCost.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost,
meshcostdata, out error, ref warning))
{
client.SendAgentAlertMessage("Unable to upload asset. missing information.", false);
LLSDAssetUploadError resperror = new LLSDAssetUploadError();
resperror.message = error;
resperror.identifier = UUID.Zero;
LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
errorResponse.uploader = "";
errorResponse.state = "error";
errorResponse.error = resperror;
lock (m_ModelCost)
m_FileAgentInventoryState = FileAgentInventoryState.idle;
return errorResponse;
}
uint textures_cost = (uint)llsdRequest.asset_resources.texture_list.Array.Count;
textures_cost *= (uint)mm.UploadCharge;
cost += textures_cost;
cost = modelcost;
}
else
{
cost = (uint)mm.UploadCharge;
cost = baseCost;
}
if (cost > 0 && mm != null)
{
// check for test upload
if (m_ForceFreeTestUpload) // all are test
{
if (!(assetName.Length > 5 && assetName.StartsWith("TEST-"))) // has normal name lets change it
assetName = "TEST-" + assetName;
IsAtestUpload = true;
}
else if (m_enableFreeTestUpload) // only if prefixed with "TEST-"
{
IsAtestUpload = (assetName.Length > 5 && assetName.StartsWith("TEST-"));
}
if(IsAtestUpload) // let user know, still showing cost estimation
warning += "Upload will have no cost, for testing purposes only. Other uses are prohibited. Items will not work after 48 hours or on other regions";
// check funds
else
{
if (!mm.UploadCovered(client.AgentId, (int)cost))
{
client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false);
LLSDAssetUploadError resperror = new LLSDAssetUploadError();
resperror.message = "Insuficient funds";
resperror.identifier = UUID.Zero;
LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
errorResponse.uploader = "";
errorResponse.state = "error";
errorResponse.error = resperror;
lock (m_ModelCost)
m_FileAgentInventoryState = FileAgentInventoryState.idle;
return errorResponse;
}
}
}
if (client != null && warning != String.Empty)
client.SendAgentAlertMessage(warning, true);
}
}
string assetName = llsdRequest.name;
string assetDes = llsdRequest.description;
string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
UUID newAsset = UUID.Random();
UUID newInvItem = UUID.Random();
UUID parentFolder = llsdRequest.folder_id;
string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
UUID texturesFolder = UUID.Zero;
AssetUploaderWithCost uploader =
new AssetUploaderWithCost(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost);
if(!IsAtestUpload && m_enableModelUploadTextureToInventory)
texturesFolder = llsdRequest.texture_folder_id;
AssetUploader uploader =
new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost,
texturesFolder, nreqtextures, nreqmeshs, nreqinstances, IsAtestUpload);
m_HostCapsObj.HttpListener.AddStreamHandler(
new BinaryStreamHandler(
@ -536,25 +661,17 @@ namespace OpenSim.Region.ClientStack.Linden
uploadResponse.state = "upload";
uploadResponse.upload_price = (int)cost;
// use fake values for now
if (llsdRequest.asset_type == "mesh")
{
uploadResponse.data = new LLSDAssetUploadResponseData();
uploadResponse.data.model_streaming_cost = 1.0;
uploadResponse.data.simulation_cost = 1.5;
uploadResponse.data.physics_cost = 2.0;
uploadResponse.data.resource_cost = 3.0;
uploadResponse.data.upload_price_breakdown.mesh_instance = 1;
uploadResponse.data.upload_price_breakdown.mesh_physics = 2;
uploadResponse.data.upload_price_breakdown.mesh_streaming = 3;
uploadResponse.data.upload_price_breakdown.texture = 5;
uploadResponse.data.upload_price_breakdown.model = 4;
uploadResponse.data = meshcostdata;
}
uploader.OnUpLoad += UploadCompleteHandler;
return uploadResponse;
lock (m_ModelCost)
m_FileAgentInventoryState = FileAgentInventoryState.waitUpload;
return uploadResponse;
}
/// <summary>
@ -565,8 +682,14 @@ namespace OpenSim.Region.ClientStack.Linden
/// <param name="data"></param>
public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
string assetType, uint cost)
string assetType, int cost,
UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
bool IsAtestUpload, ref string error)
{
lock (m_ModelCost)
m_FileAgentInventoryState = FileAgentInventoryState.processUpload;
m_log.DebugFormat(
"[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}",
assetID, inventoryItem, inventoryType, assetType);
@ -574,30 +697,60 @@ namespace OpenSim.Region.ClientStack.Linden
sbyte assType = 0;
sbyte inType = 0;
IClientAPI client = null;
UUID owner_id = m_HostCapsObj.AgentID;
UUID creatorID;
bool istest = IsAtestUpload && m_enableFreeTestUpload && (cost > 0);
bool restrictPerms = m_RestrictFreeTestUploadPerms && istest;
if (istest && m_testAssetsCreatorID != UUID.Zero)
creatorID = m_testAssetsCreatorID;
else
creatorID = owner_id;
string creatorIDstr = creatorID.ToString();
IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
if (mm != null)
{
// make sure client still has enougth credit
if (!mm.UploadCovered(m_HostCapsObj.AgentID, (int)cost))
{
error = "Insufficient funds.";
return;
}
}
// strings to types
if (inventoryType == "sound")
{
inType = 1;
assType = 1;
inType = (sbyte)InventoryType.Sound;
assType = (sbyte)AssetType.Sound;
}
else if (inventoryType == "animation")
{
inType = 19;
assType = 20;
inType = (sbyte)InventoryType.Animation;
assType = (sbyte)AssetType.Animation;
}
else if (inventoryType == "wearable")
{
inType = 18;
inType = (sbyte)InventoryType.Wearable;
switch (assetType)
{
case "bodypart":
assType = 13;
assType = (sbyte)AssetType.Bodypart;
break;
case "clothing":
assType = 5;
assType = (sbyte)AssetType.Clothing;
break;
}
}
else if (inventoryType == "object")
{
if (assetType == "mesh") // this code for now is for mesh models uploads only
{
inType = (sbyte)InventoryType.Object;
assType = (sbyte)AssetType.Object;
@ -605,27 +758,116 @@ namespace OpenSim.Region.ClientStack.Linden
List<Vector3> positions = new List<Vector3>();
List<Quaternion> rotations = new List<Quaternion>();
OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
// compare and get updated information
bool mismatchError = true;
while (mismatchError)
{
mismatchError = false;
}
if (mismatchError)
{
error = "Upload and fee estimation information don't match";
lock (m_ModelCost)
m_FileAgentInventoryState = FileAgentInventoryState.idle;
return;
}
OSDArray instance_list = (OSDArray)request["instance_list"];
OSDArray mesh_list = (OSDArray)request["mesh_list"];
OSDArray texture_list = (OSDArray)request["texture_list"];
SceneObjectGroup grp = null;
// create and store texture assets
bool doTextInv = (!istest && m_enableModelUploadTextureToInventory &&
texturesFolder != UUID.Zero);
List<UUID> textures = new List<UUID>();
if (doTextInv)
m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
if(client == null) // don't put textures in inventory if there is no client
doTextInv = false;
for (int i = 0; i < texture_list.Count; i++)
{
AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, "");
AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, creatorIDstr);
textureAsset.Data = texture_list[i].AsBinary();
if (istest)
textureAsset.Local = true;
m_assetService.Store(textureAsset);
textures.Add(textureAsset.FullID);
if (doTextInv)
{
string name = assetName;
if (name.Length > 25)
name = name.Substring(0, 24);
name += "_Texture#" + i.ToString();
InventoryItemBase texitem = new InventoryItemBase();
texitem.Owner = m_HostCapsObj.AgentID;
texitem.CreatorId = creatorIDstr;
texitem.CreatorData = String.Empty;
texitem.ID = UUID.Random();
texitem.AssetID = textureAsset.FullID;
texitem.Description = "mesh model texture";
texitem.Name = name;
texitem.AssetType = (int)AssetType.Texture;
texitem.InvType = (int)InventoryType.Texture;
texitem.Folder = texturesFolder;
texitem.CurrentPermissions
= (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
texitem.BasePermissions = (uint)PermissionMask.All;
texitem.EveryOnePermissions = 0;
texitem.NextPermissions = (uint)PermissionMask.All;
texitem.CreationDate = Util.UnixTimeSinceEpoch();
m_Scene.AddInventoryItem(client, texitem);
texitem = null;
}
}
// create and store meshs assets
List<UUID> meshAssets = new List<UUID>();
for (int i = 0; i < mesh_list.Count; i++)
{
AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, creatorIDstr);
meshAsset.Data = mesh_list[i].AsBinary();
if (istest)
meshAsset.Local = true;
m_assetService.Store(meshAsset);
meshAssets.Add(meshAsset.FullID);
}
int skipedMeshs = 0;
// build prims from instances
for (int i = 0; i < instance_list.Count; i++)
{
OSDMap inner_instance_list = (OSDMap)instance_list[i];
// skip prims that are 2 small
Vector3 scale = inner_instance_list["scale"].AsVector3();
if (scale.X < m_PrimScaleMin || scale.Y < m_PrimScaleMin || scale.Z < m_PrimScaleMin)
{
skipedMeshs++;
continue;
}
PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
Primitive.TextureEntry textureEntry
= new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
OSDMap inner_instance_list = (OSDMap)instance_list[i];
OSDArray face_list = (OSDArray)inner_instance_list["face_list"];
for (uint face = 0; face < face_list.Count; face++)
@ -669,22 +911,33 @@ namespace OpenSim.Region.ClientStack.Linden
pbs.TextureEntry = textureEntry.GetBytes();
AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, "");
meshAsset.Data = mesh_list[i].AsBinary();
m_assetService.Store(meshAsset);
bool hasmesh = false;
if (inner_instance_list.ContainsKey("mesh")) // seems to happen always but ...
{
int meshindx = inner_instance_list["mesh"].AsInteger();
if (meshAssets.Count > meshindx)
{
pbs.SculptEntry = true;
pbs.SculptTexture = meshAsset.FullID;
pbs.SculptType = (byte)SculptType.Mesh;
pbs.SculptData = meshAsset.Data;
pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction
// data will be requested from asset on rez (i hope)
hasmesh = true;
}
}
Vector3 position = inner_instance_list["position"].AsVector3();
Vector3 scale = inner_instance_list["scale"].AsVector3();
Quaternion rotation = inner_instance_list["rotation"].AsQuaternion();
// no longer used - begin ------------------------
// for now viwers do send fixed defaults
// but this may change
// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
byte physicsShapeType = (byte)PhysShapeType.prim; // default for mesh is simple convex
if(hasmesh)
physicsShapeType = (byte) PhysShapeType.convex; // default for mesh is simple convex
// int material = inner_instance_list["material"].AsInteger();
byte material = (byte)Material.Wood;
// no longer used - begin ------------------------
// int mesh = inner_instance_list["mesh"].AsInteger();
// OSDMap permissions = (OSDMap)inner_instance_list["permissions"];
@ -700,24 +953,42 @@ namespace OpenSim.Region.ClientStack.Linden
// int owner_mask = permissions["owner_mask"].AsInteger();
// no longer used - end ------------------------
UUID owner_id = m_HostCapsObj.AgentID;
SceneObjectPart prim
= new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero);
prim.Scale = scale;
prim.OffsetPosition = position;
rotations.Add(rotation);
positions.Add(position);
prim.UUID = UUID.Random();
prim.CreatorID = owner_id;
prim.CreatorID = creatorID;
prim.OwnerID = owner_id;
prim.GroupID = UUID.Zero;
prim.LastOwnerID = prim.OwnerID;
prim.LastOwnerID = creatorID;
prim.CreationDate = Util.UnixTimeSinceEpoch();
if (grp == null)
prim.Name = assetName;
else
prim.Name = assetName + "#" + i.ToString();
if (restrictPerms)
{
prim.BaseMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
prim.EveryoneMask = 0;
prim.GroupMask = 0;
prim.NextOwnerMask = 0;
prim.OwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
}
if(istest)
prim.Description = "For testing only. Other uses are prohibited";
else
prim.Description = "";
prim.Material = material;
prim.PhysicsShapeType = physicsShapeType;
// prim.BaseMask = (uint)base_mask;
// prim.EveryoneMask = (uint)everyone_mask;
// prim.GroupMask = (uint)group_mask;
@ -725,36 +996,63 @@ namespace OpenSim.Region.ClientStack.Linden
// prim.OwnerMask = (uint)owner_mask;
if (grp == null)
{
grp = new SceneObjectGroup(prim);
grp.LastOwnerID = creatorID;
}
else
grp.AddPart(prim);
}
// Fix first link number
Vector3 rootPos = positions[0];
if (grp.Parts.Length > 1)
{
// Fix first link number
grp.RootPart.LinkNum++;
Vector3 rootPos = positions[0];
grp.AbsolutePosition = rootPos;
for (int i = 0; i < positions.Count; i++)
Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]);
Quaternion tmprot;
Vector3 offset;
// fix children rotations and positions
for (int i = 1; i < rotations.Count; i++)
{
Vector3 offset = positions[i] - rootPos;
tmprot = rotations[i];
tmprot = rootRotConj * tmprot;
grp.Parts[i].RotationOffset = tmprot;
offset = positions[i] - rootPos;
offset *= rootRotConj;
grp.Parts[i].OffsetPosition = offset;
}
for (int i = 0; i < rotations.Count; i++)
grp.AbsolutePosition = rootPos;
grp.UpdateGroupRotationR(rotations[0]);
}
else
{
if (i != 0)
grp.Parts[i].RotationOffset = rotations[i];
grp.AbsolutePosition = rootPos;
grp.UpdateGroupRotationR(rotations[0]);
}
grp.UpdateGroupRotationR(rotations[0]);
data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
}
else // not a mesh model
{
m_log.ErrorFormat("[CAPS Asset Upload] got unsuported assetType for object upload");
return;
}
}
AssetBase asset;
asset = new AssetBase(assetID, assetName, assType, m_HostCapsObj.AgentID.ToString());
asset = new AssetBase(assetID, assetName, assType, creatorIDstr);
asset.Data = data;
if (istest)
asset.Local = true;
if (AddNewAsset != null)
AddNewAsset(asset);
else if (m_assetService != null)
@ -762,10 +1060,16 @@ namespace OpenSim.Region.ClientStack.Linden
InventoryItemBase item = new InventoryItemBase();
item.Owner = m_HostCapsObj.AgentID;
item.CreatorId = m_HostCapsObj.AgentID.ToString();
item.CreatorId = creatorIDstr;
item.CreatorData = String.Empty;
item.ID = inventoryItem;
item.AssetID = asset.FullID;
if (istest)
{
item.Description = "For testing only. Other uses are prohibited";
item.Flags = (uint) (InventoryItemFlags.SharedSingleReference);
}
else
item.Description = assetDescription;
item.Name = assetName;
item.AssetType = assType;
@ -774,18 +1078,60 @@ namespace OpenSim.Region.ClientStack.Linden
// If we set PermissionMask.All then when we rez the item the next permissions will replace the current
// (owner) permissions. This becomes a problem if next permissions are changed.
if (restrictPerms)
{
item.CurrentPermissions
= (uint)(PermissionMask.Move | PermissionMask.Modify);
item.BasePermissions = (uint)(PermissionMask.Move | PermissionMask.Modify);
item.EveryOnePermissions = 0;
item.NextPermissions = 0;
}
else
{
item.CurrentPermissions
= (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
item.BasePermissions = (uint)PermissionMask.All;
item.EveryOnePermissions = 0;
item.NextPermissions = (uint)PermissionMask.All;
}
item.CreationDate = Util.UnixTimeSinceEpoch();
m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
if (AddNewInventoryItem != null)
{
AddNewInventoryItem(m_HostCapsObj.AgentID, item, cost);
if (istest)
{
m_Scene.AddInventoryItem(client, item);
/*
AddNewInventoryItem(m_HostCapsObj.AgentID, item, 0);
if (client != null)
client.SendAgentAlertMessage("Upload will have no cost, for personal test purposes only. Other uses are forbiden. Items may not work on a another region" , true);
*/
}
else
{
AddNewInventoryItem(m_HostCapsObj.AgentID, item, (uint)cost);
if (client != null)
{
// let users see anything.. i don't so far
string str;
if (cost > 0)
// dont remember where is money unit name to put here
str = "Upload complete. charged " + cost.ToString() + "$";
else
str = "Upload complete";
client.SendAgentAlertMessage(str, true);
}
}
}
lock (m_ModelCost)
m_FileAgentInventoryState = FileAgentInventoryState.idle;
}
/// <summary>
@ -1098,6 +1444,7 @@ namespace OpenSim.Region.ClientStack.Linden
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public event UpLoadedAsset OnUpLoad;
private UpLoadedAsset handlerUpLoad = null;
@ -1112,11 +1459,21 @@ namespace OpenSim.Region.ClientStack.Linden
private string m_invType = String.Empty;
private string m_assetType = String.Empty;
private int m_cost;
private string m_error = String.Empty;
private Timer m_timeoutTimer = new Timer();
private UUID m_texturesFolder;
private int m_nreqtextures;
private int m_nreqmeshs;
private int m_nreqinstances;
private bool m_IsAtestUpload;
public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem,
UUID parentFolderID, string invType, string assetType, string path,
IHttpServer httpServer, bool dumpAssetsToFile)
IHttpServer httpServer, bool dumpAssetsToFile,
int totalCost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
bool IsAtestUpload)
{
m_assetName = assetName;
m_assetDes = description;
@ -1128,6 +1485,13 @@ namespace OpenSim.Region.ClientStack.Linden
m_assetType = assetType;
m_invType = invType;
m_dumpAssetsToFile = dumpAssetsToFile;
m_cost = totalCost;
m_texturesFolder = texturesFolder;
m_nreqtextures = nreqtextures;
m_nreqmeshs = nreqmeshs;
m_nreqinstances = nreqinstances;
m_IsAtestUpload = IsAtestUpload;
m_timeoutTimer.Elapsed += TimedOut;
m_timeoutTimer.Interval = 120000;
@ -1147,14 +1511,15 @@ namespace OpenSim.Region.ClientStack.Linden
UUID inv = inventoryItemID;
string res = String.Empty;
LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
/*
uploadComplete.new_asset = newAssetID.ToString();
uploadComplete.new_inventory_item = inv;
uploadComplete.state = "complete";
res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
httpListener.RemoveStreamHandler("POST", uploaderPath);
*/
m_timeoutTimer.Stop();
httpListener.RemoveStreamHandler("POST", uploaderPath);
// TODO: probably make this a better set of extensions here
string extension = ".jp2";
@ -1170,9 +1535,40 @@ namespace OpenSim.Region.ClientStack.Linden
handlerUpLoad = OnUpLoad;
if (handlerUpLoad != null)
{
handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType);
handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType,
m_cost, m_texturesFolder, m_nreqtextures, m_nreqmeshs, m_nreqinstances, m_IsAtestUpload, ref m_error);
}
if (m_IsAtestUpload)
{
LLSDAssetUploadError resperror = new LLSDAssetUploadError();
resperror.message = "Upload SUCESSEFULL for testing purposes only. Other uses are prohibited. Item will not work after 48 hours or on other regions";
resperror.identifier = inv;
uploadComplete.error = resperror;
uploadComplete.state = "Upload4Testing";
}
else
{
if (m_error == String.Empty)
{
uploadComplete.new_asset = newAssetID.ToString();
uploadComplete.new_inventory_item = inv;
// if (m_texturesFolder != UUID.Zero)
// uploadComplete.new_texture_folder_id = m_texturesFolder;
uploadComplete.state = "complete";
}
else
{
LLSDAssetUploadError resperror = new LLSDAssetUploadError();
resperror.message = m_error;
resperror.identifier = inv;
uploadComplete.error = resperror;
uploadComplete.state = "failed";
}
}
res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
return res;
}

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)
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")]
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 Scene m_scene;
@ -64,8 +72,8 @@ namespace OpenSim.Region.ClientStack.Linden
private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
private static Thread[] m_workerThreads = null;
private static OpenMetaverse.BlockingQueue<PollServiceTextureEventArgs> m_queue =
new OpenMetaverse.BlockingQueue<PollServiceTextureEventArgs>();
private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
new OpenMetaverse.BlockingQueue<aPollRequest>();
#region ISharedRegionModule Members
@ -104,7 +112,7 @@ namespace OpenSim.Region.ClientStack.Linden
String.Format("TextureWorkerThread{0}", i),
ThreadPriority.Normal,
false,
true,
false,
null,
int.MaxValue);
}
@ -129,7 +137,8 @@ namespace OpenSim.Region.ClientStack.Linden
~GetTextureModule()
{
foreach (Thread t in m_workerThreads)
t.Abort();
Watchdog.AbortThread(t.ManagedThreadId);
}
private class PollServiceTextureEventArgs : PollServiceEventArgs
@ -142,40 +151,50 @@ namespace OpenSim.Region.ClientStack.Linden
private Scene m_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;
HasEvents = (x, y) => { return this.responses.ContainsKey(x); };
GetEvents = (x, y, s) =>
HasEvents = (x, y) =>
{
lock (responses)
return responses.ContainsKey(x);
};
GetEvents = (x, y) =>
{
lock (responses)
{
try
{
return this.responses[x];
return responses[x];
}
finally
{
responses.Remove(x);
}
}
};
Request = (x, y) =>
{
y["RequestID"] = x.ToString();
lock (this.requests)
this.requests.Add(y);
aPollRequest reqinfo = new aPollRequest();
reqinfo.thepoll = this;
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) =>
{
lock (this.requests)
/*
lock (requests)
{
Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
requests.Remove(request);
}
*/
Hashtable response = new Hashtable();
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 request = null;
try
{
lock (this.requests)
{
request = requests[0];
requests.RemoveAt(0);
}
}
catch
{
return;
}
UUID requestID = new UUID(request["RequestID"].ToString());
UUID requestID = requestinfo.reqID;
// If the avatar is gone, don't bother to get the texture
if (m_scene.GetScenePresence(Id) == null)
@ -219,12 +224,14 @@ namespace OpenSim.Region.ClientStack.Linden
response["keepalive"] = false;
response["reusecontext"] = false;
lock (responses)
responses[requestID] = response;
return;
}
response = m_getTextureHandler.Handle(request);
response = m_getTextureHandler.Handle(requestinfo.request);
lock (responses)
responses[requestID] = response;
}
}
@ -234,7 +241,6 @@ namespace OpenSim.Region.ClientStack.Linden
string capUrl = "/CAPS/" + UUID.Random() + "/";
// 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);
args.Type = PollServiceEventArgs.EventType.Texture;
@ -270,11 +276,10 @@ namespace OpenSim.Region.ClientStack.Linden
{
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");
OSDMap data = new OSDMap();
ScenePresence sp = m_scene.GetScenePresence(m_agentID);
data["username"] = sp.Firstname + "." + sp.Lastname;
data["display_name_next_update"] = new OSDDate(DateTime.Now);
data["legacy_first_name"] = sp.Firstname;
// ScenePresence sp = m_scene.GetScenePresence(m_agentID);
// data["username"] = sp.Firstname + "." + sp.Lastname;
// data["display_name_next_update"] = new OSDDate(DateTime.Now);
// data["legacy_first_name"] = sp.Firstname;
data["mesh_upload_status"] = "valid";
data["display_name"] = sp.Firstname + " " + sp.Lastname;
data["legacy_last_name"] = sp.Lastname;
data["id"] = m_agentID;
data["is_display_name_default"] = true;
// data["display_name"] = sp.Firstname + " " + sp.Lastname;
// data["legacy_last_name"] = sp.Lastname;
// data["id"] = m_agentID;
// data["is_display_name_default"] = true;
//Send back data
Hashtable responsedata = new Hashtable();

View File

@ -52,6 +52,13 @@ namespace OpenSim.Region.ClientStack.Linden
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
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 Scene m_scene;
@ -64,8 +71,8 @@ namespace OpenSim.Region.ClientStack.Linden
private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
private static Thread[] m_workerThreads = null;
private static OpenMetaverse.BlockingQueue<PollServiceInventoryEventArgs> m_queue =
new OpenMetaverse.BlockingQueue<PollServiceInventoryEventArgs>();
private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
new OpenMetaverse.BlockingQueue<aPollRequest>();
#region ISharedRegionModule Members
@ -131,49 +138,52 @@ namespace OpenSim.Region.ClientStack.Linden
~WebFetchInvDescModule()
{
foreach (Thread t in m_workerThreads)
t.Abort();
Watchdog.AbortThread(t.ManagedThreadId);
}
private class PollServiceInventoryEventArgs : PollServiceEventArgs
{
private List<Hashtable> requests =
new List<Hashtable>();
private Dictionary<UUID, Hashtable> responses =
new Dictionary<UUID, Hashtable>();
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); };
GetEvents = (x, y, s) =>
HasEvents = (x, y) => { lock (responses) return responses.ContainsKey(x); };
GetEvents = (x, y) =>
{
lock (responses)
{
try
{
return this.responses[x];
return responses[x];
}
finally
{
responses.Remove(x);
}
}
};
Request = (x, y) =>
{
y["RequestID"] = x.ToString();
lock (this.requests)
this.requests.Add(y);
aPollRequest reqinfo = new aPollRequest();
reqinfo.thepoll = this;
reqinfo.reqID = x;
reqinfo.request = y;
m_queue.Enqueue(this);
m_queue.Enqueue(reqinfo);
};
NoEvents = (x, y) =>
{
lock (this.requests)
/*
lock (requests)
{
Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
requests.Remove(request);
}
*/
Hashtable response = new Hashtable();
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;
try
{
lock (this.requests)
{
request = requests[0];
requests.RemoveAt(0);
}
}
catch
{
return;
}
UUID requestID = new UUID(request["RequestID"].ToString());
UUID requestID = requestinfo.reqID;
Hashtable response = new Hashtable();
@ -212,8 +207,10 @@ namespace OpenSim.Region.ClientStack.Linden
response["keepalive"] = 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);
lock (responses)
responses[requestID] = response;
}
}
@ -223,7 +220,6 @@ namespace OpenSim.Region.ClientStack.Linden
string capUrl = "/CAPS/" + UUID.Random() + "/";
// Register this as a poll service
// absurd large timeout to tune later to make a bit less than viewer
PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(agentID);
args.Type = PollServiceEventArgs.EventType.Inventory;
@ -259,9 +255,9 @@ namespace OpenSim.Region.ClientStack.Linden
{
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);
}
/// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
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;
@ -2078,6 +2083,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// TODO: don't create new blocks if recycling an old packet
InventoryReply.AgentData.AgentID = AgentId;
InventoryReply.AgentData.SimApproved = true;
InventoryReply.AgentData.TransactionID = transactionID;
InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1];
InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock();
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,
string description, string name, sbyte invType,
sbyte type, byte wearableType, uint nextOwnerMask)
@ -153,6 +153,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
uploader.RequestCreateInventoryItem(
remoteClient, folderID, callbackID,
description, name, invType, type, wearableType, nextOwnerMask);
return true;
}
public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient,

View File

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

View File

@ -256,7 +256,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
if (sp.IsChildAgent)
return;
sp.ControllingClient.Kick(reason);
sp.Scene.IncomingCloseAgent(sp.UUID);
sp.MakeChildAgent();
sp.ControllingClient.Close();
}
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,
// 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);
}

View File

@ -186,8 +186,18 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
if (folder == null || folder.Owner != remoteClient.AgentId)
return;
if (transactionID == UUID.Zero)
if (transactionID != UUID.Zero)
{
IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule;
if (agentTransactions != null)
{
if (agentTransactions.HandleItemCreationFromTransaction(
remoteClient, transactionID, folderID, callbackID, description,
name, invType, assetType, wearableType, nextOwnerMask))
return;
}
}
ScenePresence presence;
if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence))
{
@ -206,7 +216,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
m_Scene.AssetService.Store(asset);
m_Scene.CreateNewInventoryItem(
remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
name, description, 0, callbackID, asset, invType, nextOwnerMask, creationDate);
name, description, 0, callbackID, asset, invType, nextOwnerMask, creationDate,transactionID);
}
else
{
@ -215,17 +225,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
remoteClient.AgentId);
}
}
else
{
IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule;
if (agentTransactions != null)
{
agentTransactions.HandleItemCreationFromTransaction(
remoteClient, transactionID, folderID, callbackID, description,
name, invType, assetType, wearableType, nextOwnerMask);
}
}
}
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;
RequestData requestData = null;

View File

@ -36,7 +36,7 @@ namespace OpenSim.Region.Framework.Interfaces
void HandleItemUpdateFromTransaction(IClientAPI remoteClient, UUID transactionID,
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,
sbyte type, byte wearableType, uint nextOwnerMask);

View File

@ -904,11 +904,22 @@ namespace OpenSim.Region.Framework.Scenes
public void CreateNewInventoryItem(
IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
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(
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>
@ -933,7 +944,7 @@ namespace OpenSim.Region.Framework.Scenes
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)
uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate,UUID transationID)
{
InventoryItemBase item = new InventoryItemBase();
item.Owner = remoteClient.AgentId;
@ -956,7 +967,7 @@ namespace OpenSim.Region.Framework.Scenes
if (AddInventoryItem(item))
{
remoteClient.SendInventoryItemCreateUpdate(item, callbackID);
remoteClient.SendInventoryItemCreateUpdate(item, transationID, callbackID);
}
else
{

View File

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

View File

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

View File

@ -1103,6 +1103,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
}
public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
{
}
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)
{
}

View File

@ -902,7 +902,7 @@ namespace OpenSim.Region.Physics.OdePlugin
axis.X = (axis.X > 0) ? 1f : 0f;
axis.Y = (axis.Y > 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);
}
else

View File

@ -10149,31 +10149,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
UUID key = new UUID();
if (UUID.TryParse(id, out key))
{
try
{
/*
SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
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();
SceneObjectPart part = World.GetSceneObjectPart(key);
if (part != null)
return part.ParentGroup.GetMass();
// the object is null so the key is for an avatar
ScenePresence avatar = World.GetScenePresence(key);
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
}
}
return 0;

View File

@ -443,7 +443,15 @@ namespace OpenSim.Server.Handlers.Simulation
// subclasses can override this
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 System;
using System.Threading;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
@ -50,7 +51,7 @@ namespace OpenSim.Services.Connectors
private IImprovedAssetCache m_Cache = null;
private int m_retryCounter;
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);
// 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 Thread[] m_fetchThreads;
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.Interval = 60000;
@ -112,6 +115,14 @@ namespace OpenSim.Services.Connectors
m_UriMap[prefix] = groupHost;
//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)
@ -261,6 +272,66 @@ namespace OpenSim.Services.Connectors
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)
{
string uri = MapServer(id) + "/assets/" + id;
@ -293,52 +364,11 @@ namespace OpenSim.Services.Connectors
m_AssetHandlers.Add(id, handlers);
}
bool success = false;
try
{
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);
}
QueuedAssetRequest request = new QueuedAssetRequest();
request.id = id;
request.uri = uri;
handlers.Invoke(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();
}
}
m_requestQueue.Enqueue(request);
}
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)
{
}

View File

@ -162,6 +162,7 @@
<Reference name="XMLRPC" path="../../../../bin/"/>
<Reference name="log4net" path="../../../../bin/"/>
<Reference name="HttpServer_OpenSim" path="../../../../bin/"/>
<Reference name="SmartThreadPool"/>
<Files>
<Match pattern="*.cs" recurse="true">
@ -1713,6 +1714,7 @@
<Reference name="Nini" path="../../../../../bin/"/>
<Reference name="log4net" path="../../../../../bin/"/>
<Reference name="Nini" path="../../../../../bin/"/>
<Reference name="zlib.net" path="../../../../../bin/"/>
<Files>
<Match pattern="*.cs" recurse="true">