aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs31
-rw-r--r--OpenSim/Capabilities/LLSDAssetUploadComplete.cs3
-rw-r--r--OpenSim/Capabilities/LLSDAssetUploadRequest.cs4
-rw-r--r--OpenSim/Capabilities/LLSDAssetUploadResponse.cs10
-rw-r--r--OpenSim/Framework/AssetBase.cs3
-rw-r--r--OpenSim/Framework/Console/RemoteConsole.cs2
-rw-r--r--OpenSim/Framework/IClientAPI.cs1
-rw-r--r--OpenSim/Framework/PriorityQueue.cs20
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs5
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs4
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs67
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs810
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs671
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs93
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs16
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs82
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs8
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs6
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs57
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs19
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs8
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs7
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs4
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs40
-rw-r--r--OpenSim/Server/Handlers/Simulation/AgentHandlers.cs10
-rw-r--r--OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs104
-rw-r--r--OpenSim/Tests/Common/Mock/TestClient.cs4
35 files changed, 1634 insertions, 474 deletions
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
index 7b4e957..c275d87 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -187,7 +187,11 @@ namespace OpenSim.Capabilities.Handlers
187 response["headers"] = headers; 187 response["headers"] = headers;
188 188
189 string range = String.Empty; 189 string range = String.Empty;
190 if (((Hashtable)request["headers"])["Range"] != null) 190
191 if (((Hashtable)request["headers"])["range"] != null)
192 range = (string)((Hashtable)request["headers"])["range"];
193
194 else if (((Hashtable)request["headers"])["Range"] != null)
191 range = (string)((Hashtable)request["headers"])["Range"]; 195 range = (string)((Hashtable)request["headers"])["Range"];
192 196
193 if (!String.IsNullOrEmpty(range)) // JP2's only 197 if (!String.IsNullOrEmpty(range)) // JP2's only
@@ -227,17 +231,22 @@ namespace OpenSim.Capabilities.Handlers
227 231
228// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); 232// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
229 233
230 // Always return PartialContent, even if the range covered the entire data length
231 // We were accidentally sending back 404 before in this situation
232 // https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
233 // entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
234 response["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent;
235 response["content-type"] = texture.Metadata.ContentType; 234 response["content-type"] = texture.Metadata.ContentType;
236 headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length); 235
237 236 if (start == 0 && len == texture.Data.Length) // well redudante maybe
238 byte[] d = new byte[len]; 237 {
239 Array.Copy(texture.Data, start, d, 0, len); 238 response["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
240 response["bin_response_data"] = d; 239 response["bin_response_data"] = texture.Data;
240 }
241 else
242 {
243 response["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent;
244 headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length);
245
246 byte[] d = new byte[len];
247 Array.Copy(texture.Data, start, d, 0, len);
248 response["bin_response_data"] = d;
249 }
241// response.Body.Write(texture.Data, start, len); 250// response.Body.Write(texture.Data, start, len);
242 } 251 }
243 } 252 }
diff --git a/OpenSim/Capabilities/LLSDAssetUploadComplete.cs b/OpenSim/Capabilities/LLSDAssetUploadComplete.cs
index ab6cee5..ae8eb09 100644
--- a/OpenSim/Capabilities/LLSDAssetUploadComplete.cs
+++ b/OpenSim/Capabilities/LLSDAssetUploadComplete.cs
@@ -30,12 +30,15 @@ using OpenMetaverse;
30 30
31namespace OpenSim.Framework.Capabilities 31namespace OpenSim.Framework.Capabilities
32{ 32{
33
33 [LLSDType("MAP")] 34 [LLSDType("MAP")]
34 public class LLSDAssetUploadComplete 35 public class LLSDAssetUploadComplete
35 { 36 {
36 public string new_asset = String.Empty; 37 public string new_asset = String.Empty;
37 public UUID new_inventory_item = UUID.Zero; 38 public UUID new_inventory_item = UUID.Zero;
39// public UUID new_texture_folder_id = UUID.Zero;
38 public string state = String.Empty; 40 public string state = String.Empty;
41 public LLSDAssetUploadError error = null;
39 //public bool success = false; 42 //public bool success = false;
40 43
41 public LLSDAssetUploadComplete() 44 public LLSDAssetUploadComplete()
diff --git a/OpenSim/Capabilities/LLSDAssetUploadRequest.cs b/OpenSim/Capabilities/LLSDAssetUploadRequest.cs
index f981bf0..6779cc1 100644
--- a/OpenSim/Capabilities/LLSDAssetUploadRequest.cs
+++ b/OpenSim/Capabilities/LLSDAssetUploadRequest.cs
@@ -45,6 +45,10 @@ namespace OpenSim.Framework.Capabilities
45 public string asset_type = String.Empty; 45 public string asset_type = String.Empty;
46 public string description = String.Empty; 46 public string description = String.Empty;
47 public UUID folder_id = UUID.Zero; 47 public UUID folder_id = UUID.Zero;
48 public UUID texture_folder_id = UUID.Zero;
49 public int next_owner_mask = 0;
50 public int group_mask = 0;
51 public int everyone_mask = 0;
48 public string inventory_type = String.Empty; 52 public string inventory_type = String.Empty;
49 public string name = String.Empty; 53 public string name = String.Empty;
50 public LLSDAssetResource asset_resources = new LLSDAssetResource(); 54 public LLSDAssetResource asset_resources = new LLSDAssetResource();
diff --git a/OpenSim/Capabilities/LLSDAssetUploadResponse.cs b/OpenSim/Capabilities/LLSDAssetUploadResponse.cs
index 18285b5..7c4bc97 100644
--- a/OpenSim/Capabilities/LLSDAssetUploadResponse.cs
+++ b/OpenSim/Capabilities/LLSDAssetUploadResponse.cs
@@ -26,10 +26,18 @@
26 */ 26 */
27 27
28using System; 28using System;
29using OpenMetaverse;
29 30
30namespace OpenSim.Framework.Capabilities 31namespace OpenSim.Framework.Capabilities
31{ 32{
32 [OSDMap] 33 [OSDMap]
34 public class LLSDAssetUploadError
35 {
36 public string message = String.Empty;
37 public UUID identifier = UUID.Zero;
38 }
39
40 [OSDMap]
33 public class LLSDAssetUploadResponsePricebrkDown 41 public class LLSDAssetUploadResponsePricebrkDown
34 { 42 {
35 public int mesh_streaming; 43 public int mesh_streaming;
@@ -56,11 +64,13 @@ namespace OpenSim.Framework.Capabilities
56 public string state = String.Empty; 64 public string state = String.Empty;
57 public int upload_price = 0; 65 public int upload_price = 0;
58 public LLSDAssetUploadResponseData data = null; 66 public LLSDAssetUploadResponseData data = null;
67 public LLSDAssetUploadError error = null;
59 public LLSDAssetUploadResponse() 68 public LLSDAssetUploadResponse()
60 { 69 {
61 } 70 }
62 } 71 }
63 72
73
64 [OSDMap] 74 [OSDMap]
65 public class LLSDNewFileAngentInventoryVariablePriceReplyResponse 75 public class LLSDNewFileAngentInventoryVariablePriceReplyResponse
66 { 76 {
diff --git a/OpenSim/Framework/AssetBase.cs b/OpenSim/Framework/AssetBase.cs
index ff240be..5da8e11 100644
--- a/OpenSim/Framework/AssetBase.cs
+++ b/OpenSim/Framework/AssetBase.cs
@@ -150,7 +150,8 @@ namespace OpenSim.Framework
150 Type == (sbyte)AssetType.SnapshotFolder || 150 Type == (sbyte)AssetType.SnapshotFolder ||
151 Type == (sbyte)AssetType.TrashFolder || 151 Type == (sbyte)AssetType.TrashFolder ||
152 Type == (sbyte)AssetType.ImageJPEG || 152 Type == (sbyte)AssetType.ImageJPEG ||
153 Type == (sbyte) AssetType.ImageTGA || 153 Type == (sbyte)AssetType.ImageTGA ||
154 Type == (sbyte)AssetType.Mesh ||
154 Type == (sbyte) AssetType.LSLBytecode); 155 Type == (sbyte) AssetType.LSLBytecode);
155 } 156 }
156 } 157 }
diff --git a/OpenSim/Framework/Console/RemoteConsole.cs b/OpenSim/Framework/Console/RemoteConsole.cs
index 50eb173..3e3c2b3 100644
--- a/OpenSim/Framework/Console/RemoteConsole.cs
+++ b/OpenSim/Framework/Console/RemoteConsole.cs
@@ -425,7 +425,7 @@ namespace OpenSim.Framework.Console
425 return false; 425 return false;
426 } 426 }
427 427
428 private Hashtable GetEvents(UUID RequestID, UUID sessionID, string request) 428 private Hashtable GetEvents(UUID RequestID, UUID sessionID)
429 { 429 {
430 ConsoleConnection c = null; 430 ConsoleConnection c = null;
431 431
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 91f36a5..4ae533e 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -1171,6 +1171,7 @@ namespace OpenSim.Framework
1171 /// </summary> 1171 /// </summary>
1172 /// <param name="Item"></param> 1172 /// <param name="Item"></param>
1173 void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId); 1173 void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId);
1174 void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId);
1174 1175
1175 void SendRemoveInventoryItem(UUID itemID); 1176 void SendRemoveInventoryItem(UUID itemID);
1176 1177
diff --git a/OpenSim/Framework/PriorityQueue.cs b/OpenSim/Framework/PriorityQueue.cs
index e7a7f7f..e4f1111 100644
--- a/OpenSim/Framework/PriorityQueue.cs
+++ b/OpenSim/Framework/PriorityQueue.cs
@@ -45,7 +45,8 @@ namespace OpenSim.Framework
45 /// <summary> 45 /// <summary>
46 /// Total number of queues (priorities) available 46 /// Total number of queues (priorities) available
47 /// </summary> 47 /// </summary>
48 public const uint NumberOfQueues = 12; 48
49 public const uint NumberOfQueues = 12; // includes immediate queues, m_queueCounts need to be set acording
49 50
50 /// <summary> 51 /// <summary>
51 /// Number of queuest (priorities) that are processed immediately 52 /// Number of queuest (priorities) that are processed immediately
@@ -60,7 +61,8 @@ namespace OpenSim.Framework
60 // each pass. weighted towards the higher priority queues 61 // each pass. weighted towards the higher priority queues
61 private uint m_nextQueue = 0; 62 private uint m_nextQueue = 0;
62 private uint m_countFromQueue = 0; 63 private uint m_countFromQueue = 0;
63 private uint[] m_queueCounts = { 8, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1 }; 64 // first queues are imediate, so no counts
65 private uint[] m_queueCounts = {0, 0, 8, 4, 4, 2, 2, 2, 2, 1, 1, 1};
64 66
65 // next request is a counter of the number of updates queued, it provides 67 // next request is a counter of the number of updates queued, it provides
66 // a total ordering on the updates coming through the queue and is more 68 // a total ordering on the updates coming through the queue and is more
@@ -137,7 +139,7 @@ namespace OpenSim.Framework
137 /// </summary> 139 /// </summary>
138 public bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue) 140 public bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue)
139 { 141 {
140 // If there is anything in priority queue 0, return it first no 142 // If there is anything in imediate queues, return it first no
141 // matter what else. Breaks fairness. But very useful. 143 // matter what else. Breaks fairness. But very useful.
142 for (int iq = 0; iq < NumberOfImmediateQueues; iq++) 144 for (int iq = 0; iq < NumberOfImmediateQueues; iq++)
143 { 145 {
@@ -172,14 +174,13 @@ namespace OpenSim.Framework
172 } 174 }
173 175
174 // Find the next non-immediate queue with updates in it 176 // Find the next non-immediate queue with updates in it
175 for (int i = 0; i < NumberOfQueues; ++i) 177 for (uint i = NumberOfImmediateQueues; i < NumberOfQueues; ++i)
176 { 178 {
177 m_nextQueue = (uint)((m_nextQueue + 1) % NumberOfQueues); 179 m_nextQueue++;
178 m_countFromQueue = m_queueCounts[m_nextQueue]; 180 if(m_nextQueue >= NumberOfQueues)
181 m_nextQueue = NumberOfImmediateQueues;
179 182
180 // if this is one of the immediate queues, just skip it 183 m_countFromQueue = m_queueCounts[m_nextQueue];
181 if (m_nextQueue < NumberOfImmediateQueues)
182 continue;
183 184
184 if (m_heaps[m_nextQueue].Count > 0) 185 if (m_heaps[m_nextQueue].Count > 0)
185 { 186 {
@@ -189,7 +190,6 @@ namespace OpenSim.Framework
189 m_lookupTable.Remove(item.Value.Entity.LocalId); 190 m_lookupTable.Remove(item.Value.Entity.LocalId);
190 timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); 191 timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
191 value = item.Value; 192 value = item.Value;
192
193 return true; 193 return true;
194 } 194 }
195 } 195 }
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 29593e5..1d35b1a 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -334,6 +334,7 @@ namespace OpenSim.Framework.Servers.HttpServer
334 StreamReader reader = new StreamReader(requestStream, encoding); 334 StreamReader reader = new StreamReader(requestStream, encoding);
335 335
336 string requestBody = reader.ReadToEnd(); 336 string requestBody = reader.ReadToEnd();
337 reader.Close();
337 338
338 Hashtable keysvals = new Hashtable(); 339 Hashtable keysvals = new Hashtable();
339 Hashtable headervals = new Hashtable(); 340 Hashtable headervals = new Hashtable();
@@ -648,7 +649,7 @@ namespace OpenSim.Framework.Servers.HttpServer
648 // Every month or so this will wrap and give bad numbers, not really a problem 649 // Every month or so this will wrap and give bad numbers, not really a problem
649 // since its just for reporting 650 // since its just for reporting
650 int tickdiff = requestEndTick - requestStartTick; 651 int tickdiff = requestEndTick - requestStartTick;
651 if (tickdiff > 3000 && requestHandler.Name != "GetTexture") 652 if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture"))
652 { 653 {
653 m_log.InfoFormat( 654 m_log.InfoFormat(
654 "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms", 655 "[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
1555 else 1556 else
1556 responseString = (string)responsedata["str_response_string"]; 1557 responseString = (string)responsedata["str_response_string"];
1557 contentType = (string)responsedata["content_type"]; 1558 contentType = (string)responsedata["content_type"];
1559 if (responseString == null)
1560 responseString = String.Empty;
1558 } 1561 }
1559 catch 1562 catch
1560 { 1563 {
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
index a80b1d7..d0a37d0 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
@@ -34,7 +34,7 @@ namespace OpenSim.Framework.Servers.HttpServer
34 public delegate void RequestMethod(UUID requestID, Hashtable request); 34 public delegate void RequestMethod(UUID requestID, Hashtable request);
35 public delegate bool HasEventsMethod(UUID requestID, UUID pId); 35 public delegate bool HasEventsMethod(UUID requestID, UUID pId);
36 36
37 public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId, string request); 37 public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId);
38 38
39 public delegate Hashtable NoEventsMethod(UUID requestID, UUID pId); 39 public delegate Hashtable NoEventsMethod(UUID requestID, UUID pId);
40 40
@@ -46,7 +46,7 @@ namespace OpenSim.Framework.Servers.HttpServer
46 public RequestMethod Request; 46 public RequestMethod Request;
47 public UUID Id; 47 public UUID Id;
48 public int TimeOutms; 48 public int TimeOutms;
49 public EventType Type; 49 public EventType Type;
50 50
51 public enum EventType : int 51 public enum EventType : int
52 { 52 {
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index db088e7..4be8bf4 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -33,6 +33,7 @@ using log4net;
33using HttpServer; 33using HttpServer;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Monitoring; 35using OpenSim.Framework.Monitoring;
36using Amib.Threading;
36 37
37 38
38/* 39/*
@@ -185,6 +186,8 @@ namespace OpenSim.Framework.Servers.HttpServer
185 private bool m_running = true; 186 private bool m_running = true;
186 private int slowCount = 0; 187 private int slowCount = 0;
187 188
189 private SmartThreadPool m_threadPool = new SmartThreadPool(20000, 12, 2);
190
188// private int m_timeout = 1000; // increase timeout 250; now use the event one 191// private int m_timeout = 1000; // increase timeout 250; now use the event one
189 192
190 public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout) 193 public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout)
@@ -202,7 +205,7 @@ namespace OpenSim.Framework.Servers.HttpServer
202 String.Format("PollServiceWorkerThread{0}", i), 205 String.Format("PollServiceWorkerThread{0}", i),
203 ThreadPriority.Normal, 206 ThreadPriority.Normal,
204 false, 207 false,
205 true, 208 false,
206 null, 209 null,
207 int.MaxValue); 210 int.MaxValue);
208 } 211 }
@@ -275,15 +278,7 @@ namespace OpenSim.Framework.Servers.HttpServer
275 Thread.Sleep(1000); // let the world move 278 Thread.Sleep(1000); // let the world move
276 279
277 foreach (Thread t in m_workerThreads) 280 foreach (Thread t in m_workerThreads)
278 { 281 Watchdog.AbortThread(t.ManagedThreadId);
279 try
280 {
281 t.Abort();
282 }
283 catch
284 {
285 }
286 }
287 282
288 try 283 try
289 { 284 {
@@ -326,13 +321,9 @@ namespace OpenSim.Framework.Servers.HttpServer
326 321
327 private void PoolWorkerJob() 322 private void PoolWorkerJob()
328 { 323 {
329 PollServiceHttpRequest req;
330 StreamReader str;
331
332// while (true)
333 while (m_running) 324 while (m_running)
334 { 325 {
335 req = m_requests.Dequeue(5000); 326 PollServiceHttpRequest req = m_requests.Dequeue(5000);
336 327
337 Watchdog.UpdateThread(); 328 Watchdog.UpdateThread();
338 if (req != null) 329 if (req != null)
@@ -341,35 +332,41 @@ namespace OpenSim.Framework.Servers.HttpServer
341 { 332 {
342 if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id)) 333 if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
343 { 334 {
344 try 335 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
345 { 336
346 str = new StreamReader(req.Request.Body); 337 if (responsedata == null)
347 }
348 catch (System.ArgumentException)
349 {
350 // Stream was not readable means a child agent
351 // was closed due to logout, leaving the
352 // Event Queue request orphaned.
353 continue; 338 continue;
354 }
355 339
356 try 340 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.Normal)
357 { 341 {
358 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id, str.ReadToEnd()); 342 try
359 DoHTTPGruntWork(m_server, req, responsedata); 343 {
344 DoHTTPGruntWork(m_server, req, responsedata);
345 }
346 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
347 {
348 // Ignore it, no need to reply
349 }
360 } 350 }
361 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream 351 else
362 { 352 {
363 // Ignore it, no need to reply 353 m_threadPool.QueueWorkItem(x =>
354 {
355 try
356 {
357 DoHTTPGruntWork(m_server, req, responsedata);
358 }
359 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
360 {
361 // Ignore it, no need to reply
362 }
363
364 return null;
365 }, null);
364 } 366 }
365
366 str.Close();
367
368 } 367 }
369 else 368 else
370 { 369 {
371// if ((Environment.TickCount - req.RequestTime) > m_timeout)
372
373 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) 370 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
374 { 371 {
375 DoHTTPGruntWork(m_server, req, 372 DoHTTPGruntWork(m_server, req,
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 580c005..c705f10 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -54,8 +54,10 @@ using OSDMap = OpenMetaverse.StructuredData.OSDMap;
54namespace OpenSim.Region.ClientStack.Linden 54namespace OpenSim.Region.ClientStack.Linden
55{ 55{
56 public delegate void UpLoadedAsset( 56 public delegate void UpLoadedAsset(
57 string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder, 57 string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder,
58 byte[] data, string inventoryType, string assetType); 58 byte[] data, string inventoryType, string assetType,
59 int cost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
60 bool IsAtestUpload, ref string error);
59 61
60 public delegate UUID UpdateItem(UUID itemID, byte[] data); 62 public delegate UUID UpdateItem(UUID itemID, byte[] data);
61 63
@@ -87,6 +89,7 @@ namespace OpenSim.Region.ClientStack.Linden
87 89
88 private Scene m_Scene; 90 private Scene m_Scene;
89 private Caps m_HostCapsObj; 91 private Caps m_HostCapsObj;
92 private ModelCost m_ModelCost;
90 93
91 private static readonly string m_requestPath = "0000/"; 94 private static readonly string m_requestPath = "0000/";
92 // private static readonly string m_mapLayerPath = "0001/"; 95 // private static readonly string m_mapLayerPath = "0001/";
@@ -115,12 +118,50 @@ namespace OpenSim.Region.ClientStack.Linden
115 private IAssetService m_assetService; 118 private IAssetService m_assetService;
116 private bool m_dumpAssetsToFile = false; 119 private bool m_dumpAssetsToFile = false;
117 private string m_regionName; 120 private string m_regionName;
121
118 private int m_levelUpload = 0; 122 private int m_levelUpload = 0;
119 123
124 private bool m_enableFreeTestUpload = false; // allows "TEST-" prefix hack
125 private bool m_ForceFreeTestUpload = false; // forces all uploads to be test
126
127 private bool m_enableModelUploadTextureToInventory = false; // place uploaded textures also in inventory
128 // may not be visible till relog
129
130 private bool m_RestrictFreeTestUploadPerms = false; // reduces also the permitions. Needs a creator defined!!
131 private UUID m_testAssetsCreatorID = UUID.Zero;
132
133 private float m_PrimScaleMin = 0.001f;
134
135 private enum FileAgentInventoryState : int
136 {
137 idle = 0,
138 processRequest = 1,
139 waitUpload = 2,
140 processUpload = 3
141 }
142 private FileAgentInventoryState m_FileAgentInventoryState = FileAgentInventoryState.idle;
143
120 public BunchOfCaps(Scene scene, Caps caps) 144 public BunchOfCaps(Scene scene, Caps caps)
121 { 145 {
122 m_Scene = scene; 146 m_Scene = scene;
123 m_HostCapsObj = caps; 147 m_HostCapsObj = caps;
148
149 // create a model upload cost provider
150 m_ModelCost = new ModelCost();
151 // tell it about scene object limits
152 m_ModelCost.NonPhysicalPrimScaleMax = m_Scene.m_maxNonphys;
153 m_ModelCost.PhysicalPrimScaleMax = m_Scene.m_maxPhys;
154
155// m_ModelCost.ObjectLinkedPartsMax = ??
156// m_ModelCost.PrimScaleMin = ??
157
158 m_PrimScaleMin = m_ModelCost.PrimScaleMin;
159 float modelTextureUploadFactor = m_ModelCost.ModelTextureCostFactor;
160 float modelUploadFactor = m_ModelCost.ModelMeshCostFactor;
161 float modelMinUploadCostFactor = m_ModelCost.ModelMinCostFactor;
162 float modelPrimCreationCost = m_ModelCost.primCreationCost;
163 float modelMeshByteCost = m_ModelCost.bytecost;
164
124 IConfigSource config = m_Scene.Config; 165 IConfigSource config = m_Scene.Config;
125 if (config != null) 166 if (config != null)
126 { 167 {
@@ -135,6 +176,37 @@ namespace OpenSim.Region.ClientStack.Linden
135 { 176 {
136 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); 177 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
137 } 178 }
179 // economy for model upload
180 IConfig EconomyConfig = config.Configs["Economy"];
181 if (EconomyConfig != null)
182 {
183 modelUploadFactor = EconomyConfig.GetFloat("MeshModelUploadCostFactor", modelUploadFactor);
184 modelTextureUploadFactor = EconomyConfig.GetFloat("MeshModelUploadTextureCostFactor", modelTextureUploadFactor);
185 modelMinUploadCostFactor = EconomyConfig.GetFloat("MeshModelMinCostFactor", modelMinUploadCostFactor);
186 // next 2 are normalized so final cost is afected by modelUploadFactor above and normal cost
187 modelPrimCreationCost = EconomyConfig.GetFloat("ModelPrimCreationCost", modelPrimCreationCost);
188 modelMeshByteCost = EconomyConfig.GetFloat("ModelMeshByteCost", modelMeshByteCost);
189
190 m_enableModelUploadTextureToInventory = EconomyConfig.GetBoolean("MeshModelAllowTextureToInventory", m_enableModelUploadTextureToInventory);
191
192 m_RestrictFreeTestUploadPerms = EconomyConfig.GetBoolean("m_RestrictFreeTestUploadPerms", m_RestrictFreeTestUploadPerms);
193 m_enableFreeTestUpload = EconomyConfig.GetBoolean("AllowFreeTestUpload", m_enableFreeTestUpload);
194 m_ForceFreeTestUpload = EconomyConfig.GetBoolean("ForceFreeTestUpload", m_ForceFreeTestUpload);
195 string testcreator = EconomyConfig.GetString("TestAssetsCreatorID", "");
196 if (testcreator != "")
197 {
198 UUID id;
199 UUID.TryParse(testcreator, out id);
200 if (id != null)
201 m_testAssetsCreatorID = id;
202 }
203
204 m_ModelCost.ModelMeshCostFactor = modelUploadFactor;
205 m_ModelCost.ModelTextureCostFactor = modelTextureUploadFactor;
206 m_ModelCost.ModelMinCostFactor = modelMinUploadCostFactor;
207 m_ModelCost.primCreationCost = modelPrimCreationCost;
208 m_ModelCost.bytecost = modelMeshByteCost;
209 }
138 } 210 }
139 211
140 m_assetService = m_Scene.AssetService; 212 m_assetService = m_Scene.AssetService;
@@ -146,6 +218,8 @@ namespace OpenSim.Region.ClientStack.Linden
146 ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset; 218 ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset;
147 TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset; 219 TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset;
148 GetClient = m_Scene.SceneGraph.GetControllingClient; 220 GetClient = m_Scene.SceneGraph.GetControllingClient;
221
222 m_FileAgentInventoryState = FileAgentInventoryState.idle;
149 } 223 }
150 224
151 /// <summary> 225 /// <summary>
@@ -191,7 +265,6 @@ namespace OpenSim.Region.ClientStack.Linden
191 { 265 {
192 try 266 try
193 { 267 {
194 // I don't think this one works...
195 m_HostCapsObj.RegisterHandler( 268 m_HostCapsObj.RegisterHandler(
196 "NewFileAgentInventory", 269 "NewFileAgentInventory",
197 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>( 270 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>(
@@ -213,9 +286,7 @@ namespace OpenSim.Region.ClientStack.Linden
213 IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost); 286 IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost);
214 m_HostCapsObj.RegisterHandler("GetObjectCost", getObjectCostHandler); 287 m_HostCapsObj.RegisterHandler("GetObjectCost", getObjectCostHandler);
215 IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected); 288 IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected);
216 m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler); 289 m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler);
217
218
219 290
220 m_HostCapsObj.RegisterHandler( 291 m_HostCapsObj.RegisterHandler(
221 "CopyInventoryFromNotecard", 292 "CopyInventoryFromNotecard",
@@ -387,37 +458,6 @@ namespace OpenSim.Region.ClientStack.Linden
387 return UUID.Zero; 458 return UUID.Zero;
388 } 459 }
389 460
390 private delegate void UploadWithCostCompleteDelegate(string assetName,
391 string assetDescription, UUID assetID, UUID inventoryItem,
392 UUID parentFolder, byte[] data, string inventoryType,
393 string assetType, uint cost);
394
395 private class AssetUploaderWithCost : AssetUploader
396 {
397 private uint m_cost;
398
399 public event UploadWithCostCompleteDelegate OnUpLoad;
400
401 public AssetUploaderWithCost(string assetName, string description, UUID assetID,
402 UUID inventoryItem, UUID parentFolderID, string invType, string assetType,
403 string path, IHttpServer httpServer, bool dumpAssetsToFile, uint cost) :
404 base(assetName, description, assetID, inventoryItem, parentFolderID,
405 invType, assetType, path, httpServer, dumpAssetsToFile)
406 {
407 m_cost = cost;
408
409 base.OnUpLoad += UploadCompleteHandler;
410 }
411
412 private void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
413 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
414 string assetType)
415 {
416 OnUpLoad(assetName, assetDescription, assetID, inventoryItem, parentFolder,
417 data, inventoryType, assetType, m_cost);
418 }
419 }
420
421 /// <summary> 461 /// <summary>
422 /// 462 ///
423 /// </summary> 463 /// </summary>
@@ -428,7 +468,47 @@ namespace OpenSim.Region.ClientStack.Linden
428 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString()); 468 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString());
429 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type); 469 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type);
430 470
431 uint cost = 0; 471 // start by getting the client
472 IClientAPI client = null;
473 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
474
475 // check current state so we only have one service at a time
476 lock (m_ModelCost)
477 {
478 switch (m_FileAgentInventoryState)
479 {
480 case FileAgentInventoryState.processRequest:
481 case FileAgentInventoryState.processUpload:
482 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
483 resperror.message = "Uploader busy processing previus request";
484 resperror.identifier = UUID.Zero;
485
486 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
487 errorResponse.uploader = "";
488 errorResponse.state = "error";
489 errorResponse.error = resperror;
490 return errorResponse;
491 break;
492 case FileAgentInventoryState.waitUpload:
493 // todo stop current uploader server
494 break;
495 case FileAgentInventoryState.idle:
496 default:
497 break;
498 }
499
500 m_FileAgentInventoryState = FileAgentInventoryState.processRequest;
501 }
502
503 int cost = 0;
504 int nreqtextures = 0;
505 int nreqmeshs= 0;
506 int nreqinstances = 0;
507 bool IsAtestUpload = false;
508
509 string assetName = llsdRequest.name;
510
511 LLSDAssetUploadResponseData meshcostdata = new LLSDAssetUploadResponseData();
432 512
433 if (llsdRequest.asset_type == "texture" || 513 if (llsdRequest.asset_type == "texture" ||
434 llsdRequest.asset_type == "animation" || 514 llsdRequest.asset_type == "animation" ||
@@ -436,83 +516,128 @@ namespace OpenSim.Region.ClientStack.Linden
436 llsdRequest.asset_type == "sound") 516 llsdRequest.asset_type == "sound")
437 { 517 {
438 ScenePresence avatar = null; 518 ScenePresence avatar = null;
439 IClientAPI client = null;
440 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar); 519 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar);
441 520
442 // check user level 521 // check user level
443 if (avatar != null) 522 if (avatar != null)
444 { 523 {
445 client = avatar.ControllingClient;
446
447 if (avatar.UserLevel < m_levelUpload) 524 if (avatar.UserLevel < m_levelUpload)
448 { 525 {
449 if (client != null) 526 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
450 client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false); 527 resperror.message = "Insufficient permissions to upload";
528 resperror.identifier = UUID.Zero;
451 529
452 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 530 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
453 errorResponse.uploader = ""; 531 errorResponse.uploader = "";
454 errorResponse.state = "error"; 532 errorResponse.state = "error";
533 errorResponse.error = resperror;
534 lock (m_ModelCost)
535 m_FileAgentInventoryState = FileAgentInventoryState.idle;
455 return errorResponse; 536 return errorResponse;
456 } 537 }
457 } 538 }
458 539
459 // check funds 540 // check test upload and funds
460 if (client != null) 541 if (client != null)
461 { 542 {
462 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>(); 543 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
463 544
545 int baseCost = 0;
464 if (mm != null) 546 if (mm != null)
465 { 547 baseCost = mm.UploadCharge;
466 // XPTO: The cost should be calculated about here
467 548
468 if (llsdRequest.asset_type == "mesh") 549 string warning = String.Empty;
550
551 if (llsdRequest.asset_type == "mesh")
552 {
553 string error;
554 int modelcost;
555
556 if (!m_ModelCost.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost,
557 meshcostdata, out error, ref warning))
469 { 558 {
470 cost += 20; // Constant for now to test showing a price 559 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
560 resperror.message = error;
561 resperror.identifier = UUID.Zero;
471 562
472 if (llsdRequest.asset_resources == null) 563 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
473 { 564 errorResponse.uploader = "";
474 client.SendAgentAlertMessage("Unable to upload asset. missing information.", false); 565 errorResponse.state = "error";
566 errorResponse.error = resperror;
475 567
476 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 568 lock (m_ModelCost)
477 errorResponse.uploader = ""; 569 m_FileAgentInventoryState = FileAgentInventoryState.idle;
478 errorResponse.state = "error"; 570 return errorResponse;
479 return errorResponse; 571 }
480 } 572 cost = modelcost;
573 }
574 else
575 {
576 cost = baseCost;
577 }
481 578
482 uint textures_cost = (uint)llsdRequest.asset_resources.texture_list.Array.Count; 579 if (cost > 0 && mm != null)
483 textures_cost *= (uint)mm.UploadCharge; 580 {
581 // check for test upload
582
583 if (m_ForceFreeTestUpload) // all are test
584 {
585 if (!(assetName.Length > 5 && assetName.StartsWith("TEST-"))) // has normal name lets change it
586 assetName = "TEST-" + assetName;
484 587
485 cost += textures_cost; 588 IsAtestUpload = true;
486 } 589 }
487 else 590
591 else if (m_enableFreeTestUpload) // only if prefixed with "TEST-"
488 { 592 {
489 cost = (uint)mm.UploadCharge; 593
594 IsAtestUpload = (assetName.Length > 5 && assetName.StartsWith("TEST-"));
490 } 595 }
491 596
492 if (!mm.UploadCovered(client.AgentId, (int)cost)) 597
598 if(IsAtestUpload) // let user know, still showing cost estimation
599 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";
600
601 // check funds
602 else
493 { 603 {
494 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); 604 if (!mm.UploadCovered(client.AgentId, (int)cost))
605 {
606 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
607 resperror.message = "Insuficient funds";
608 resperror.identifier = UUID.Zero;
495 609
496 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 610 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
497 errorResponse.uploader = ""; 611 errorResponse.uploader = "";
498 errorResponse.state = "error"; 612 errorResponse.state = "error";
499 return errorResponse; 613 errorResponse.error = resperror;
614 lock (m_ModelCost)
615 m_FileAgentInventoryState = FileAgentInventoryState.idle;
616 return errorResponse;
617 }
500 } 618 }
501 } 619 }
620
621 if (client != null && warning != String.Empty)
622 client.SendAgentAlertMessage(warning, true);
502 } 623 }
503 } 624 }
504 625
505 string assetName = llsdRequest.name;
506 string assetDes = llsdRequest.description; 626 string assetDes = llsdRequest.description;
507 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; 627 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
508 UUID newAsset = UUID.Random(); 628 UUID newAsset = UUID.Random();
509 UUID newInvItem = UUID.Random(); 629 UUID newInvItem = UUID.Random();
510 UUID parentFolder = llsdRequest.folder_id; 630 UUID parentFolder = llsdRequest.folder_id;
511 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); 631 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
632 UUID texturesFolder = UUID.Zero;
633
634 if(!IsAtestUpload && m_enableModelUploadTextureToInventory)
635 texturesFolder = llsdRequest.texture_folder_id;
512 636
513 AssetUploaderWithCost uploader = 637 AssetUploader uploader =
514 new AssetUploaderWithCost(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, 638 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
515 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost); 639 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost,
640 texturesFolder, nreqtextures, nreqmeshs, nreqinstances, IsAtestUpload);
516 641
517 m_HostCapsObj.HttpListener.AddStreamHandler( 642 m_HostCapsObj.HttpListener.AddStreamHandler(
518 new BinaryStreamHandler( 643 new BinaryStreamHandler(
@@ -536,25 +661,17 @@ namespace OpenSim.Region.ClientStack.Linden
536 uploadResponse.state = "upload"; 661 uploadResponse.state = "upload";
537 uploadResponse.upload_price = (int)cost; 662 uploadResponse.upload_price = (int)cost;
538 663
539 // use fake values for now
540 if (llsdRequest.asset_type == "mesh") 664 if (llsdRequest.asset_type == "mesh")
541 { 665 {
542 uploadResponse.data = new LLSDAssetUploadResponseData(); 666 uploadResponse.data = meshcostdata;
543 uploadResponse.data.model_streaming_cost = 1.0;
544 uploadResponse.data.simulation_cost = 1.5;
545
546 uploadResponse.data.physics_cost = 2.0;
547 uploadResponse.data.resource_cost = 3.0;
548 uploadResponse.data.upload_price_breakdown.mesh_instance = 1;
549 uploadResponse.data.upload_price_breakdown.mesh_physics = 2;
550 uploadResponse.data.upload_price_breakdown.mesh_streaming = 3;
551 uploadResponse.data.upload_price_breakdown.texture = 5;
552 uploadResponse.data.upload_price_breakdown.model = 4;
553 } 667 }
554 668
555 uploader.OnUpLoad += UploadCompleteHandler; 669 uploader.OnUpLoad += UploadCompleteHandler;
556 return uploadResponse;
557 670
671 lock (m_ModelCost)
672 m_FileAgentInventoryState = FileAgentInventoryState.waitUpload;
673
674 return uploadResponse;
558 } 675 }
559 676
560 /// <summary> 677 /// <summary>
@@ -565,8 +682,14 @@ namespace OpenSim.Region.ClientStack.Linden
565 /// <param name="data"></param> 682 /// <param name="data"></param>
566 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID, 683 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
567 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, 684 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
568 string assetType, uint cost) 685 string assetType, int cost,
686 UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
687 bool IsAtestUpload, ref string error)
569 { 688 {
689
690 lock (m_ModelCost)
691 m_FileAgentInventoryState = FileAgentInventoryState.processUpload;
692
570 m_log.DebugFormat( 693 m_log.DebugFormat(
571 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}", 694 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}",
572 assetID, inventoryItem, inventoryType, assetType); 695 assetID, inventoryItem, inventoryType, assetType);
@@ -574,117 +697,247 @@ namespace OpenSim.Region.ClientStack.Linden
574 sbyte assType = 0; 697 sbyte assType = 0;
575 sbyte inType = 0; 698 sbyte inType = 0;
576 699
700 IClientAPI client = null;
701
702 UUID owner_id = m_HostCapsObj.AgentID;
703 UUID creatorID;
704
705 bool istest = IsAtestUpload && m_enableFreeTestUpload && (cost > 0);
706
707 bool restrictPerms = m_RestrictFreeTestUploadPerms && istest;
708
709 if (istest && m_testAssetsCreatorID != UUID.Zero)
710 creatorID = m_testAssetsCreatorID;
711 else
712 creatorID = owner_id;
713
714 string creatorIDstr = creatorID.ToString();
715
716 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
717 if (mm != null)
718 {
719 // make sure client still has enougth credit
720 if (!mm.UploadCovered(m_HostCapsObj.AgentID, (int)cost))
721 {
722 error = "Insufficient funds.";
723 return;
724 }
725 }
726
727 // strings to types
577 if (inventoryType == "sound") 728 if (inventoryType == "sound")
578 { 729 {
579 inType = 1; 730 inType = (sbyte)InventoryType.Sound;
580 assType = 1; 731 assType = (sbyte)AssetType.Sound;
581 } 732 }
582 else if (inventoryType == "animation") 733 else if (inventoryType == "animation")
583 { 734 {
584 inType = 19; 735 inType = (sbyte)InventoryType.Animation;
585 assType = 20; 736 assType = (sbyte)AssetType.Animation;
586 } 737 }
587 else if (inventoryType == "wearable") 738 else if (inventoryType == "wearable")
588 { 739 {
589 inType = 18; 740 inType = (sbyte)InventoryType.Wearable;
590 switch (assetType) 741 switch (assetType)
591 { 742 {
592 case "bodypart": 743 case "bodypart":
593 assType = 13; 744 assType = (sbyte)AssetType.Bodypart;
594 break; 745 break;
595 case "clothing": 746 case "clothing":
596 assType = 5; 747 assType = (sbyte)AssetType.Clothing;
597 break; 748 break;
598 } 749 }
599 } 750 }
600 else if (inventoryType == "object") 751 else if (inventoryType == "object")
601 { 752 {
602 inType = (sbyte)InventoryType.Object; 753 if (assetType == "mesh") // this code for now is for mesh models uploads only
603 assType = (sbyte)AssetType.Object;
604
605 List<Vector3> positions = new List<Vector3>();
606 List<Quaternion> rotations = new List<Quaternion>();
607 OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
608 OSDArray instance_list = (OSDArray)request["instance_list"];
609 OSDArray mesh_list = (OSDArray)request["mesh_list"];
610 OSDArray texture_list = (OSDArray)request["texture_list"];
611 SceneObjectGroup grp = null;
612
613 List<UUID> textures = new List<UUID>();
614 for (int i = 0; i < texture_list.Count; i++)
615 { 754 {
616 AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, ""); 755 inType = (sbyte)InventoryType.Object;
617 textureAsset.Data = texture_list[i].AsBinary(); 756 assType = (sbyte)AssetType.Object;
618 m_assetService.Store(textureAsset);
619 textures.Add(textureAsset.FullID);
620 }
621 757
622 for (int i = 0; i < mesh_list.Count; i++) 758 List<Vector3> positions = new List<Vector3>();
623 { 759 List<Quaternion> rotations = new List<Quaternion>();
624 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); 760 OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
625 761
626 Primitive.TextureEntry textureEntry 762 // compare and get updated information
627 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
628 OSDMap inner_instance_list = (OSDMap)instance_list[i];
629 763
630 OSDArray face_list = (OSDArray)inner_instance_list["face_list"]; 764 bool mismatchError = true;
631 for (uint face = 0; face < face_list.Count; face++) 765
766 while (mismatchError)
632 { 767 {
633 OSDMap faceMap = (OSDMap)face_list[(int)face]; 768 mismatchError = false;
634 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face); 769 }
635 if(faceMap.ContainsKey("fullbright"))
636 f.Fullbright = faceMap["fullbright"].AsBoolean();
637 if (faceMap.ContainsKey ("diffuse_color"))
638 f.RGBA = faceMap["diffuse_color"].AsColor4();
639 770
640 int textureNum = faceMap["image"].AsInteger(); 771 if (mismatchError)
641 float imagerot = faceMap["imagerot"].AsInteger(); 772 {
642 float offsets = (float)faceMap["offsets"].AsReal(); 773 error = "Upload and fee estimation information don't match";
643 float offsett = (float)faceMap["offsett"].AsReal(); 774 lock (m_ModelCost)
644 float scales = (float)faceMap["scales"].AsReal(); 775 m_FileAgentInventoryState = FileAgentInventoryState.idle;
645 float scalet = (float)faceMap["scalet"].AsReal();
646 776
647 if(imagerot != 0) 777 return;
648 f.Rotation = imagerot; 778 }
649 779
650 if(offsets != 0) 780 OSDArray instance_list = (OSDArray)request["instance_list"];
651 f.OffsetU = offsets; 781 OSDArray mesh_list = (OSDArray)request["mesh_list"];
782 OSDArray texture_list = (OSDArray)request["texture_list"];
783 SceneObjectGroup grp = null;
652 784
653 if (offsett != 0) 785 // create and store texture assets
654 f.OffsetV = offsett; 786 bool doTextInv = (!istest && m_enableModelUploadTextureToInventory &&
787 texturesFolder != UUID.Zero);
655 788
656 if (scales != 0)
657 f.RepeatU = scales;
658 789
659 if (scalet != 0) 790 List<UUID> textures = new List<UUID>();
660 f.RepeatV = scalet;
661 791
662 if (textures.Count > textureNum) 792
663 f.TextureID = textures[textureNum]; 793 if (doTextInv)
664 else 794 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
665 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
666 795
667 textureEntry.FaceTextures[face] = f; 796 if(client == null) // don't put textures in inventory if there is no client
797 doTextInv = false;
798
799 for (int i = 0; i < texture_list.Count; i++)
800 {
801 AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, creatorIDstr);
802 textureAsset.Data = texture_list[i].AsBinary();
803 if (istest)
804 textureAsset.Local = true;
805 m_assetService.Store(textureAsset);
806 textures.Add(textureAsset.FullID);
807
808 if (doTextInv)
809 {
810 string name = assetName;
811 if (name.Length > 25)
812 name = name.Substring(0, 24);
813 name += "_Texture#" + i.ToString();
814 InventoryItemBase texitem = new InventoryItemBase();
815 texitem.Owner = m_HostCapsObj.AgentID;
816 texitem.CreatorId = creatorIDstr;
817 texitem.CreatorData = String.Empty;
818 texitem.ID = UUID.Random();
819 texitem.AssetID = textureAsset.FullID;
820 texitem.Description = "mesh model texture";
821 texitem.Name = name;
822 texitem.AssetType = (int)AssetType.Texture;
823 texitem.InvType = (int)InventoryType.Texture;
824 texitem.Folder = texturesFolder;
825
826 texitem.CurrentPermissions
827 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
828
829 texitem.BasePermissions = (uint)PermissionMask.All;
830 texitem.EveryOnePermissions = 0;
831 texitem.NextPermissions = (uint)PermissionMask.All;
832 texitem.CreationDate = Util.UnixTimeSinceEpoch();
833
834 m_Scene.AddInventoryItem(client, texitem);
835 texitem = null;
836 }
837 }
838
839 // create and store meshs assets
840 List<UUID> meshAssets = new List<UUID>();
841 for (int i = 0; i < mesh_list.Count; i++)
842 {
843 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, creatorIDstr);
844 meshAsset.Data = mesh_list[i].AsBinary();
845 if (istest)
846 meshAsset.Local = true;
847 m_assetService.Store(meshAsset);
848 meshAssets.Add(meshAsset.FullID);
668 } 849 }
669 850
670 pbs.TextureEntry = textureEntry.GetBytes(); 851 int skipedMeshs = 0;
852 // build prims from instances
853 for (int i = 0; i < instance_list.Count; i++)
854 {
855 OSDMap inner_instance_list = (OSDMap)instance_list[i];
856
857 // skip prims that are 2 small
858 Vector3 scale = inner_instance_list["scale"].AsVector3();
859
860 if (scale.X < m_PrimScaleMin || scale.Y < m_PrimScaleMin || scale.Z < m_PrimScaleMin)
861 {
862 skipedMeshs++;
863 continue;
864 }
865
866 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
867
868 Primitive.TextureEntry textureEntry
869 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
870
871
872 OSDArray face_list = (OSDArray)inner_instance_list["face_list"];
873 for (uint face = 0; face < face_list.Count; face++)
874 {
875 OSDMap faceMap = (OSDMap)face_list[(int)face];
876 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face);
877 if (faceMap.ContainsKey("fullbright"))
878 f.Fullbright = faceMap["fullbright"].AsBoolean();
879 if (faceMap.ContainsKey("diffuse_color"))
880 f.RGBA = faceMap["diffuse_color"].AsColor4();
881
882 int textureNum = faceMap["image"].AsInteger();
883 float imagerot = faceMap["imagerot"].AsInteger();
884 float offsets = (float)faceMap["offsets"].AsReal();
885 float offsett = (float)faceMap["offsett"].AsReal();
886 float scales = (float)faceMap["scales"].AsReal();
887 float scalet = (float)faceMap["scalet"].AsReal();
888
889 if (imagerot != 0)
890 f.Rotation = imagerot;
891
892 if (offsets != 0)
893 f.OffsetU = offsets;
671 894
672 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, ""); 895 if (offsett != 0)
673 meshAsset.Data = mesh_list[i].AsBinary(); 896 f.OffsetV = offsett;
674 m_assetService.Store(meshAsset);
675 897
676 pbs.SculptEntry = true; 898 if (scales != 0)
677 pbs.SculptTexture = meshAsset.FullID; 899 f.RepeatU = scales;
678 pbs.SculptType = (byte)SculptType.Mesh;
679 pbs.SculptData = meshAsset.Data;
680 900
681 Vector3 position = inner_instance_list["position"].AsVector3(); 901 if (scalet != 0)
682 Vector3 scale = inner_instance_list["scale"].AsVector3(); 902 f.RepeatV = scalet;
683 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion(); 903
904 if (textures.Count > textureNum)
905 f.TextureID = textures[textureNum];
906 else
907 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
908
909 textureEntry.FaceTextures[face] = f;
910 }
911
912 pbs.TextureEntry = textureEntry.GetBytes();
913
914 bool hasmesh = false;
915 if (inner_instance_list.ContainsKey("mesh")) // seems to happen always but ...
916 {
917 int meshindx = inner_instance_list["mesh"].AsInteger();
918 if (meshAssets.Count > meshindx)
919 {
920 pbs.SculptEntry = true;
921 pbs.SculptType = (byte)SculptType.Mesh;
922 pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction
923 // data will be requested from asset on rez (i hope)
924 hasmesh = true;
925 }
926 }
927
928 Vector3 position = inner_instance_list["position"].AsVector3();
929 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion();
930
931 // for now viwers do send fixed defaults
932 // but this may change
933// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
934 byte physicsShapeType = (byte)PhysShapeType.prim; // default for mesh is simple convex
935 if(hasmesh)
936 physicsShapeType = (byte) PhysShapeType.convex; // default for mesh is simple convex
937// int material = inner_instance_list["material"].AsInteger();
938 byte material = (byte)Material.Wood;
684 939
685// no longer used - begin ------------------------ 940// no longer used - begin ------------------------
686// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
687// int material = inner_instance_list["material"].AsInteger();
688// int mesh = inner_instance_list["mesh"].AsInteger(); 941// int mesh = inner_instance_list["mesh"].AsInteger();
689 942
690// OSDMap permissions = (OSDMap)inner_instance_list["permissions"]; 943// OSDMap permissions = (OSDMap)inner_instance_list["permissions"];
@@ -699,24 +952,42 @@ namespace OpenSim.Region.ClientStack.Linden
699// UUID owner_id = permissions["owner_id"].AsUUID(); 952// UUID owner_id = permissions["owner_id"].AsUUID();
700// int owner_mask = permissions["owner_mask"].AsInteger(); 953// int owner_mask = permissions["owner_mask"].AsInteger();
701// no longer used - end ------------------------ 954// no longer used - end ------------------------
955
956
957 SceneObjectPart prim
958 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero);
959
960 prim.Scale = scale;
961 rotations.Add(rotation);
962 positions.Add(position);
963 prim.UUID = UUID.Random();
964 prim.CreatorID = creatorID;
965 prim.OwnerID = owner_id;
966 prim.GroupID = UUID.Zero;
967 prim.LastOwnerID = creatorID;
968 prim.CreationDate = Util.UnixTimeSinceEpoch();
969
970 if (grp == null)
971 prim.Name = assetName;
972 else
973 prim.Name = assetName + "#" + i.ToString();
702 974
703 UUID owner_id = m_HostCapsObj.AgentID; 975 if (restrictPerms)
976 {
977 prim.BaseMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
978 prim.EveryoneMask = 0;
979 prim.GroupMask = 0;
980 prim.NextOwnerMask = 0;
981 prim.OwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
982 }
704 983
705 SceneObjectPart prim 984 if(istest)
706 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero); 985 prim.Description = "For testing only. Other uses are prohibited";
986 else
987 prim.Description = "";
707 988
708 prim.Scale = scale; 989 prim.Material = material;
709 prim.OffsetPosition = position; 990 prim.PhysicsShapeType = physicsShapeType;
710 rotations.Add(rotation);
711 positions.Add(position);
712 prim.UUID = UUID.Random();
713 prim.CreatorID = owner_id;
714 prim.OwnerID = owner_id;
715 prim.GroupID = UUID.Zero;
716 prim.LastOwnerID = prim.OwnerID;
717 prim.CreationDate = Util.UnixTimeSinceEpoch();
718 prim.Name = assetName;
719 prim.Description = "";
720 991
721// prim.BaseMask = (uint)base_mask; 992// prim.BaseMask = (uint)base_mask;
722// prim.EveryoneMask = (uint)everyone_mask; 993// prim.EveryoneMask = (uint)everyone_mask;
@@ -724,37 +995,64 @@ namespace OpenSim.Region.ClientStack.Linden
724// prim.NextOwnerMask = (uint)next_owner_mask; 995// prim.NextOwnerMask = (uint)next_owner_mask;
725// prim.OwnerMask = (uint)owner_mask; 996// prim.OwnerMask = (uint)owner_mask;
726 997
727 if (grp == null) 998 if (grp == null)
728 grp = new SceneObjectGroup(prim); 999 {
729 else 1000 grp = new SceneObjectGroup(prim);
730 grp.AddPart(prim); 1001 grp.LastOwnerID = creatorID;
731 } 1002 }
1003 else
1004 grp.AddPart(prim);
1005 }
732 1006
733 // Fix first link number 1007 Vector3 rootPos = positions[0];
734 if (grp.Parts.Length > 1)
735 grp.RootPart.LinkNum++;
736 1008
737 Vector3 rootPos = positions[0]; 1009 if (grp.Parts.Length > 1)
738 grp.AbsolutePosition = rootPos; 1010 {
739 for (int i = 0; i < positions.Count; i++) 1011 // Fix first link number
740 { 1012 grp.RootPart.LinkNum++;
741 Vector3 offset = positions[i] - rootPos; 1013
742 grp.Parts[i].OffsetPosition = offset; 1014 Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]);
1015 Quaternion tmprot;
1016 Vector3 offset;
1017
1018 // fix children rotations and positions
1019 for (int i = 1; i < rotations.Count; i++)
1020 {
1021 tmprot = rotations[i];
1022 tmprot = rootRotConj * tmprot;
1023
1024 grp.Parts[i].RotationOffset = tmprot;
1025
1026 offset = positions[i] - rootPos;
1027
1028 offset *= rootRotConj;
1029 grp.Parts[i].OffsetPosition = offset;
1030 }
1031
1032 grp.AbsolutePosition = rootPos;
1033 grp.UpdateGroupRotationR(rotations[0]);
1034 }
1035 else
1036 {
1037 grp.AbsolutePosition = rootPos;
1038 grp.UpdateGroupRotationR(rotations[0]);
1039 }
1040
1041 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
743 } 1042 }
744 1043
745 for (int i = 0; i < rotations.Count; i++) 1044 else // not a mesh model
746 { 1045 {
747 if (i != 0) 1046 m_log.ErrorFormat("[CAPS Asset Upload] got unsuported assetType for object upload");
748 grp.Parts[i].RotationOffset = rotations[i]; 1047 return;
749 } 1048 }
750
751 grp.UpdateGroupRotationR(rotations[0]);
752 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
753 } 1049 }
754 1050
755 AssetBase asset; 1051 AssetBase asset;
756 asset = new AssetBase(assetID, assetName, assType, m_HostCapsObj.AgentID.ToString()); 1052 asset = new AssetBase(assetID, assetName, assType, creatorIDstr);
757 asset.Data = data; 1053 asset.Data = data;
1054 if (istest)
1055 asset.Local = true;
758 if (AddNewAsset != null) 1056 if (AddNewAsset != null)
759 AddNewAsset(asset); 1057 AddNewAsset(asset);
760 else if (m_assetService != null) 1058 else if (m_assetService != null)
@@ -762,11 +1060,17 @@ namespace OpenSim.Region.ClientStack.Linden
762 1060
763 InventoryItemBase item = new InventoryItemBase(); 1061 InventoryItemBase item = new InventoryItemBase();
764 item.Owner = m_HostCapsObj.AgentID; 1062 item.Owner = m_HostCapsObj.AgentID;
765 item.CreatorId = m_HostCapsObj.AgentID.ToString(); 1063 item.CreatorId = creatorIDstr;
766 item.CreatorData = String.Empty; 1064 item.CreatorData = String.Empty;
767 item.ID = inventoryItem; 1065 item.ID = inventoryItem;
768 item.AssetID = asset.FullID; 1066 item.AssetID = asset.FullID;
769 item.Description = assetDescription; 1067 if (istest)
1068 {
1069 item.Description = "For testing only. Other uses are prohibited";
1070 item.Flags = (uint) (InventoryItemFlags.SharedSingleReference);
1071 }
1072 else
1073 item.Description = assetDescription;
770 item.Name = assetName; 1074 item.Name = assetName;
771 item.AssetType = assType; 1075 item.AssetType = assType;
772 item.InvType = inType; 1076 item.InvType = inType;
@@ -774,18 +1078,60 @@ namespace OpenSim.Region.ClientStack.Linden
774 1078
775 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current 1079 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
776 // (owner) permissions. This becomes a problem if next permissions are changed. 1080 // (owner) permissions. This becomes a problem if next permissions are changed.
777 item.CurrentPermissions
778 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
779 1081
780 item.BasePermissions = (uint)PermissionMask.All; 1082 if (restrictPerms)
781 item.EveryOnePermissions = 0; 1083 {
782 item.NextPermissions = (uint)PermissionMask.All; 1084 item.CurrentPermissions
1085 = (uint)(PermissionMask.Move | PermissionMask.Modify);
1086
1087 item.BasePermissions = (uint)(PermissionMask.Move | PermissionMask.Modify);
1088 item.EveryOnePermissions = 0;
1089 item.NextPermissions = 0;
1090 }
1091 else
1092 {
1093 item.CurrentPermissions
1094 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
1095
1096 item.BasePermissions = (uint)PermissionMask.All;
1097 item.EveryOnePermissions = 0;
1098 item.NextPermissions = (uint)PermissionMask.All;
1099 }
1100
783 item.CreationDate = Util.UnixTimeSinceEpoch(); 1101 item.CreationDate = Util.UnixTimeSinceEpoch();
784 1102
1103 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
1104
785 if (AddNewInventoryItem != null) 1105 if (AddNewInventoryItem != null)
786 { 1106 {
787 AddNewInventoryItem(m_HostCapsObj.AgentID, item, cost); 1107 if (istest)
1108 {
1109 m_Scene.AddInventoryItem(client, item);
1110/*
1111 AddNewInventoryItem(m_HostCapsObj.AgentID, item, 0);
1112 if (client != null)
1113 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);
1114 */
1115 }
1116 else
1117 {
1118 AddNewInventoryItem(m_HostCapsObj.AgentID, item, (uint)cost);
1119 if (client != null)
1120 {
1121 // let users see anything.. i don't so far
1122 string str;
1123 if (cost > 0)
1124 // dont remember where is money unit name to put here
1125 str = "Upload complete. charged " + cost.ToString() + "$";
1126 else
1127 str = "Upload complete";
1128 client.SendAgentAlertMessage(str, true);
1129 }
1130 }
788 } 1131 }
1132
1133 lock (m_ModelCost)
1134 m_FileAgentInventoryState = FileAgentInventoryState.idle;
789 } 1135 }
790 1136
791 /// <summary> 1137 /// <summary>
@@ -1098,6 +1444,7 @@ namespace OpenSim.Region.ClientStack.Linden
1098 private static readonly ILog m_log = 1444 private static readonly ILog m_log =
1099 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 1445 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
1100 1446
1447
1101 public event UpLoadedAsset OnUpLoad; 1448 public event UpLoadedAsset OnUpLoad;
1102 private UpLoadedAsset handlerUpLoad = null; 1449 private UpLoadedAsset handlerUpLoad = null;
1103 1450
@@ -1112,11 +1459,21 @@ namespace OpenSim.Region.ClientStack.Linden
1112 1459
1113 private string m_invType = String.Empty; 1460 private string m_invType = String.Empty;
1114 private string m_assetType = String.Empty; 1461 private string m_assetType = String.Empty;
1462 private int m_cost;
1463 private string m_error = String.Empty;
1464
1115 private Timer m_timeoutTimer = new Timer(); 1465 private Timer m_timeoutTimer = new Timer();
1466 private UUID m_texturesFolder;
1467 private int m_nreqtextures;
1468 private int m_nreqmeshs;
1469 private int m_nreqinstances;
1470 private bool m_IsAtestUpload;
1116 1471
1117 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem, 1472 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem,
1118 UUID parentFolderID, string invType, string assetType, string path, 1473 UUID parentFolderID, string invType, string assetType, string path,
1119 IHttpServer httpServer, bool dumpAssetsToFile) 1474 IHttpServer httpServer, bool dumpAssetsToFile,
1475 int totalCost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
1476 bool IsAtestUpload)
1120 { 1477 {
1121 m_assetName = assetName; 1478 m_assetName = assetName;
1122 m_assetDes = description; 1479 m_assetDes = description;
@@ -1128,6 +1485,13 @@ namespace OpenSim.Region.ClientStack.Linden
1128 m_assetType = assetType; 1485 m_assetType = assetType;
1129 m_invType = invType; 1486 m_invType = invType;
1130 m_dumpAssetsToFile = dumpAssetsToFile; 1487 m_dumpAssetsToFile = dumpAssetsToFile;
1488 m_cost = totalCost;
1489
1490 m_texturesFolder = texturesFolder;
1491 m_nreqtextures = nreqtextures;
1492 m_nreqmeshs = nreqmeshs;
1493 m_nreqinstances = nreqinstances;
1494 m_IsAtestUpload = IsAtestUpload;
1131 1495
1132 m_timeoutTimer.Elapsed += TimedOut; 1496 m_timeoutTimer.Elapsed += TimedOut;
1133 m_timeoutTimer.Interval = 120000; 1497 m_timeoutTimer.Interval = 120000;
@@ -1147,14 +1511,15 @@ namespace OpenSim.Region.ClientStack.Linden
1147 UUID inv = inventoryItemID; 1511 UUID inv = inventoryItemID;
1148 string res = String.Empty; 1512 string res = String.Empty;
1149 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); 1513 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
1514/*
1150 uploadComplete.new_asset = newAssetID.ToString(); 1515 uploadComplete.new_asset = newAssetID.ToString();
1151 uploadComplete.new_inventory_item = inv; 1516 uploadComplete.new_inventory_item = inv;
1152 uploadComplete.state = "complete"; 1517 uploadComplete.state = "complete";
1153 1518
1154 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); 1519 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
1155 1520*/
1156 httpListener.RemoveStreamHandler("POST", uploaderPath);
1157 m_timeoutTimer.Stop(); 1521 m_timeoutTimer.Stop();
1522 httpListener.RemoveStreamHandler("POST", uploaderPath);
1158 1523
1159 // TODO: probably make this a better set of extensions here 1524 // TODO: probably make this a better set of extensions here
1160 string extension = ".jp2"; 1525 string extension = ".jp2";
@@ -1170,9 +1535,40 @@ namespace OpenSim.Region.ClientStack.Linden
1170 handlerUpLoad = OnUpLoad; 1535 handlerUpLoad = OnUpLoad;
1171 if (handlerUpLoad != null) 1536 if (handlerUpLoad != null)
1172 { 1537 {
1173 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType); 1538 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType,
1539 m_cost, m_texturesFolder, m_nreqtextures, m_nreqmeshs, m_nreqinstances, m_IsAtestUpload, ref m_error);
1174 } 1540 }
1541 if (m_IsAtestUpload)
1542 {
1543 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
1544 resperror.message = "Upload SUCESSEFULL for testing purposes only. Other uses are prohibited. Item will not work after 48 hours or on other regions";
1545 resperror.identifier = inv;
1175 1546
1547 uploadComplete.error = resperror;
1548 uploadComplete.state = "Upload4Testing";
1549 }
1550 else
1551 {
1552 if (m_error == String.Empty)
1553 {
1554 uploadComplete.new_asset = newAssetID.ToString();
1555 uploadComplete.new_inventory_item = inv;
1556 // if (m_texturesFolder != UUID.Zero)
1557 // uploadComplete.new_texture_folder_id = m_texturesFolder;
1558 uploadComplete.state = "complete";
1559 }
1560 else
1561 {
1562 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
1563 resperror.message = m_error;
1564 resperror.identifier = inv;
1565
1566 uploadComplete.error = resperror;
1567 uploadComplete.state = "failed";
1568 }
1569 }
1570
1571 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
1176 return res; 1572 return res;
1177 } 1573 }
1178 1574
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
new file mode 100644
index 0000000..4a3fae6
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
@@ -0,0 +1,671 @@
1// Proprietary code of Avination Virtual Limited
2// (c) 2012 Melanie Thielker, Leal Duarte
3//
4
5using System;
6using System.IO;
7using System.Collections;
8using System.Collections.Generic;
9using System.Text;
10
11using OpenMetaverse;
12using OpenMetaverse.StructuredData;
13
14using OpenSim.Framework;
15using OpenSim.Region.Framework;
16using OpenSim.Region.Framework.Scenes;
17using OpenSim.Framework.Capabilities;
18
19using ComponentAce.Compression.Libs.zlib;
20
21using OSDArray = OpenMetaverse.StructuredData.OSDArray;
22using OSDMap = OpenMetaverse.StructuredData.OSDMap;
23
24namespace OpenSim.Region.ClientStack.Linden
25{
26 public struct ModelPrimLimits
27 {
28
29 }
30
31 public class ModelCost
32 {
33
34 // upload fee defaults
35 // fees are normalized to 1.0
36 // this parameters scale them to basic cost ( so 1.0 translates to 10 )
37
38 public float ModelMeshCostFactor = 0.0f; // scale total cost relative to basic (excluding textures)
39 public float ModelTextureCostFactor = 1.0f; // scale textures fee to basic.
40 public float ModelMinCostFactor = 0.0f; // 0.5f; // minimum total model free excluding textures
41
42 // itens costs in normalized values
43 // ie will be multiplied by basicCost and factors above
44 public float primCreationCost = 0.002f; // extra cost for each prim creation overhead
45 // weigthed size to normalized cost
46 public float bytecost = 1e-5f;
47
48 // mesh upload fees based on compressed data sizes
49 // several data sections are counted more that once
50 // to promote user optimization
51 // following parameters control how many extra times they are added
52 // to global size.
53 // LOD meshs
54 const float medSizeWth = 1f; // 2x
55 const float lowSizeWth = 1.5f; // 2.5x
56 const float lowestSizeWth = 2f; // 3x
57 // favor potencially physical optimized meshs versus automatic decomposition
58 const float physMeshSizeWth = 6f; // counts 7x
59 const float physHullSizeWth = 8f; // counts 9x
60
61 // stream cost area factors
62 // more or less like SL
63 const float highLodFactor = 17.36f;
64 const float midLodFactor = 277.78f;
65 const float lowLodFactor = 1111.11f;
66
67 // physics cost is below, identical to SL, assuming shape type convex
68 // server cost is below identical to SL assuming non scripted non physical object
69
70 // internal
71 const int bytesPerCoord = 6; // 3 coords, 2 bytes per each
72
73 // control prims dimensions
74 public float PrimScaleMin = 0.001f;
75 public float NonPhysicalPrimScaleMax = 256f;
76 public float PhysicalPrimScaleMax = 10f;
77 public int ObjectLinkedPartsMax = 512;
78
79 // storage for a single mesh asset cost parameters
80 private class ameshCostParam
81 {
82 // LOD sizes for size dependent streaming cost
83 public int highLODSize;
84 public int medLODSize;
85 public int lowLODSize;
86 public int lowestLODSize;
87 // normalized fee based on compressed data sizes
88 public float costFee;
89 // physics cost
90 public float physicsCost;
91 }
92
93 // calculates a mesh model costs
94 // returns false on error, with a reason on parameter error
95 // resources input LLSD request
96 // basicCost input region assets upload cost
97 // totalcost returns model total upload fee
98 // meshcostdata returns detailed costs for viewer
99 public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost,
100 LLSDAssetUploadResponseData meshcostdata, out string error, ref string warning)
101 {
102 totalcost = 0;
103 error = string.Empty;
104
105 if (resources == null ||
106 resources.instance_list == null ||
107 resources.instance_list.Array.Count == 0)
108 {
109 error = "missing model information.";
110 return false;
111 }
112
113 int numberInstances = resources.instance_list.Array.Count;
114
115 if( numberInstances > ObjectLinkedPartsMax )
116 {
117 error = "Model whould have more than " + ObjectLinkedPartsMax.ToString() + " linked prims";
118 return false;
119 }
120
121 meshcostdata.model_streaming_cost = 0.0;
122 meshcostdata.simulation_cost = 0.0;
123 meshcostdata.physics_cost = 0.0;
124 meshcostdata.resource_cost = 0.0;
125
126 meshcostdata.upload_price_breakdown.mesh_instance = 0;
127 meshcostdata.upload_price_breakdown.mesh_physics = 0;
128 meshcostdata.upload_price_breakdown.mesh_streaming = 0;
129 meshcostdata.upload_price_breakdown.model = 0;
130
131 int itmp;
132
133 // textures cost
134 if (resources.texture_list != null && resources.texture_list.Array.Count > 0)
135 {
136 float textures_cost = (float)(resources.texture_list.Array.Count * basicCost);
137 textures_cost *= ModelTextureCostFactor;
138
139 itmp = (int)(textures_cost + 0.5f); // round
140 meshcostdata.upload_price_breakdown.texture = itmp;
141 totalcost += itmp;
142 }
143
144 // meshs assets cost
145 float meshsfee = 0;
146 int numberMeshs = 0;
147 bool haveMeshs = false;
148 List<ameshCostParam> meshsCosts = new List<ameshCostParam>();
149
150 if (resources.mesh_list != null && resources.mesh_list.Array.Count > 0)
151 {
152 numberMeshs = resources.mesh_list.Array.Count;
153
154 for (int i = 0; i < numberMeshs; i++)
155 {
156 ameshCostParam curCost = new ameshCostParam();
157 byte[] data = (byte[])resources.mesh_list.Array[i];
158
159 if (!MeshCost(data, curCost, out error))
160 {
161 return false;
162 }
163 meshsCosts.Add(curCost);
164 meshsfee += curCost.costFee;
165 }
166 haveMeshs = true;
167 }
168
169 // instances (prims) cost
170
171
172 int mesh;
173 int skipedSmall = 0;
174 for (int i = 0; i < numberInstances; i++)
175 {
176 Hashtable inst = (Hashtable)resources.instance_list.Array[i];
177
178 ArrayList ascale = (ArrayList)inst["scale"];
179 Vector3 scale;
180 double tmp;
181 tmp = (double)ascale[0];
182 scale.X = (float)tmp;
183 tmp = (double)ascale[1];
184 scale.Y = (float)tmp;
185 tmp = (double)ascale[2];
186 scale.Z = (float)tmp;
187
188 if (scale.X < PrimScaleMin || scale.Y < PrimScaleMin || scale.Z < PrimScaleMin)
189 {
190 skipedSmall++;
191 continue;
192 }
193
194 if (scale.X > NonPhysicalPrimScaleMax || scale.Y > NonPhysicalPrimScaleMax || scale.Z > NonPhysicalPrimScaleMax)
195 {
196 error = "Model contains parts with sides larger than " + NonPhysicalPrimScaleMax.ToString() + "m. Please ajust scale";
197 return false;
198 }
199
200 if (haveMeshs && inst.ContainsKey("mesh"))
201 {
202 mesh = (int)inst["mesh"];
203
204 if (mesh >= numberMeshs)
205 {
206 error = "Incoerent model information.";
207 return false;
208 }
209
210 // streamming cost
211
212 float sqdiam = scale.LengthSquared();
213
214 ameshCostParam curCost = meshsCosts[mesh];
215 float mesh_streaming = streamingCost(curCost, sqdiam);
216
217 meshcostdata.model_streaming_cost += mesh_streaming;
218 meshcostdata.physics_cost += curCost.physicsCost;
219 }
220 else // instance as no mesh ??
221 {
222 // to do later if needed
223 meshcostdata.model_streaming_cost += 0.5f;
224 meshcostdata.physics_cost += 1.0f;
225 }
226
227 // assume unscripted and static prim server cost
228 meshcostdata.simulation_cost += 0.5f;
229 // charge for prims creation
230 meshsfee += primCreationCost;
231 }
232
233 if (skipedSmall > 0)
234 {
235 if (skipedSmall > numberInstances / 2)
236 {
237 error = "Model contains too many prims smaller than " + PrimScaleMin.ToString() +
238 "m minimum allowed size. Please check scalling";
239 return false;
240 }
241 else
242 warning += skipedSmall.ToString() + " of the requested " +numberInstances.ToString() +
243 " model prims will not upload because they are smaller than " + PrimScaleMin.ToString() +
244 "m minimum allowed size. Please check scalling ";
245 }
246
247 if (meshcostdata.physics_cost <= meshcostdata.model_streaming_cost)
248 meshcostdata.resource_cost = meshcostdata.model_streaming_cost;
249 else
250 meshcostdata.resource_cost = meshcostdata.physics_cost;
251
252 if (meshcostdata.resource_cost < meshcostdata.simulation_cost)
253 meshcostdata.resource_cost = meshcostdata.simulation_cost;
254
255 // scale cost
256 // at this point a cost of 1.0 whould mean basic cost
257 meshsfee *= ModelMeshCostFactor;
258
259 if (meshsfee < ModelMinCostFactor)
260 meshsfee = ModelMinCostFactor;
261
262 // actually scale it to basic cost
263 meshsfee *= (float)basicCost;
264
265 meshsfee += 0.5f; // rounding
266
267 totalcost += (int)meshsfee;
268
269 // breakdown prices
270 // don't seem to be in use so removed code for now
271
272 return true;
273 }
274
275 // single mesh asset cost
276 private bool MeshCost(byte[] data, ameshCostParam cost, out string error)
277 {
278 cost.highLODSize = 0;
279 cost.medLODSize = 0;
280 cost.lowLODSize = 0;
281 cost.lowestLODSize = 0;
282 cost.physicsCost = 0.0f;
283 cost.costFee = 0.0f;
284
285 error = string.Empty;
286
287 if (data == null || data.Length == 0)
288 {
289 error = "Missing model information.";
290 return false;
291 }
292
293 OSD meshOsd = null;
294 int start = 0;
295
296 error = "Invalid model data";
297
298 using (MemoryStream ms = new MemoryStream(data))
299 {
300 try
301 {
302 OSD osd = OSDParser.DeserializeLLSDBinary(ms);
303 if (osd is OSDMap)
304 meshOsd = (OSDMap)osd;
305 else
306 return false;
307 }
308 catch (Exception e)
309 {
310 return false;
311 }
312 start = (int)ms.Position;
313 }
314
315 OSDMap map = (OSDMap)meshOsd;
316 OSDMap tmpmap;
317
318 int highlod_size = 0;
319 int medlod_size = 0;
320 int lowlod_size = 0;
321 int lowestlod_size = 0;
322 int skin_size = 0;
323
324 int hulls_size = 0;
325 int phys_nhulls;
326 int phys_hullsvertices = 0;
327
328 int physmesh_size = 0;
329 int phys_ntriangles = 0;
330
331 int submesh_offset = -1;
332
333 if (map.ContainsKey("physics_convex"))
334 {
335 tmpmap = (OSDMap)map["physics_convex"];
336 if (tmpmap.ContainsKey("offset"))
337 submesh_offset = tmpmap["offset"].AsInteger() + start;
338 if (tmpmap.ContainsKey("size"))
339 hulls_size = tmpmap["size"].AsInteger();
340 }
341
342 if (submesh_offset < 0 || hulls_size == 0)
343 {
344 error = "Missing physics_convex block";
345 return false;
346 }
347
348 if (!hulls(data, submesh_offset, hulls_size, out phys_hullsvertices, out phys_nhulls))
349 {
350 error = "Bad physics_convex block";
351 return false;
352 }
353
354 submesh_offset = -1;
355
356 // only look for LOD meshs sizes
357
358 if (map.ContainsKey("high_lod"))
359 {
360 tmpmap = (OSDMap)map["high_lod"];
361 // see at least if there is a offset for this one
362 if (tmpmap.ContainsKey("offset"))
363 submesh_offset = tmpmap["offset"].AsInteger() + start;
364 if (tmpmap.ContainsKey("size"))
365 highlod_size = tmpmap["size"].AsInteger();
366 }
367
368 if (submesh_offset < 0 || highlod_size <= 0)
369 {
370 error = "Missing high_lod block";
371 return false;
372 }
373
374 bool haveprev = true;
375
376 if (map.ContainsKey("medium_lod"))
377 {
378 tmpmap = (OSDMap)map["medium_lod"];
379 if (tmpmap.ContainsKey("size"))
380 medlod_size = tmpmap["size"].AsInteger();
381 else
382 haveprev = false;
383 }
384
385 if (haveprev && map.ContainsKey("low_lod"))
386 {
387 tmpmap = (OSDMap)map["low_lod"];
388 if (tmpmap.ContainsKey("size"))
389 lowlod_size = tmpmap["size"].AsInteger();
390 else
391 haveprev = false;
392 }
393
394 if (haveprev && map.ContainsKey("lowest_lod"))
395 {
396 tmpmap = (OSDMap)map["lowest_lod"];
397 if (tmpmap.ContainsKey("size"))
398 lowestlod_size = tmpmap["size"].AsInteger();
399 }
400
401 if (map.ContainsKey("skin"))
402 {
403 tmpmap = (OSDMap)map["skin"];
404 if (tmpmap.ContainsKey("size"))
405 skin_size = tmpmap["size"].AsInteger();
406 }
407
408 cost.highLODSize = highlod_size;
409 cost.medLODSize = medlod_size;
410 cost.lowLODSize = lowlod_size;
411 cost.lowestLODSize = lowestlod_size;
412
413 submesh_offset = -1;
414
415 tmpmap = null;
416 if(map.ContainsKey("physics_mesh"))
417 tmpmap = (OSDMap)map["physics_mesh"];
418 else if (map.ContainsKey("physics_shape")) // old naming
419 tmpmap = (OSDMap)map["physics_shape"];
420
421 if(tmpmap != null)
422 {
423 if (tmpmap.ContainsKey("offset"))
424 submesh_offset = tmpmap["offset"].AsInteger() + start;
425 if (tmpmap.ContainsKey("size"))
426 physmesh_size = tmpmap["size"].AsInteger();
427
428 if (submesh_offset >= 0 || physmesh_size > 0)
429 {
430
431 if (!submesh(data, submesh_offset, physmesh_size, out phys_ntriangles))
432 {
433 error = "Model data parsing error";
434 return false;
435 }
436 }
437 }
438
439 // upload is done in convex shape type so only one hull
440 phys_hullsvertices++;
441 cost.physicsCost = 0.04f * phys_hullsvertices;
442
443 float sfee;
444
445 sfee = data.Length; // start with total compressed data size
446
447 // penalize lod meshs that should be more builder optimized
448 sfee += medSizeWth * medlod_size;
449 sfee += lowSizeWth * lowlod_size;
450 sfee += lowestSizeWth * lowlod_size;
451
452 // physics
453 // favor potencial optimized meshs versus automatic decomposition
454 if (physmesh_size != 0)
455 sfee += physMeshSizeWth * (physmesh_size + hulls_size / 4); // reduce cost of mandatory convex hull
456 else
457 sfee += physHullSizeWth * hulls_size;
458
459 // bytes to money
460 sfee *= bytecost;
461
462 cost.costFee = sfee;
463 return true;
464 }
465
466 // parses a LOD or physics mesh component
467 private bool submesh(byte[] data, int offset, int size, out int ntriangles)
468 {
469 ntriangles = 0;
470
471 OSD decodedMeshOsd = new OSD();
472 byte[] meshBytes = new byte[size];
473 System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
474 try
475 {
476 using (MemoryStream inMs = new MemoryStream(meshBytes))
477 {
478 using (MemoryStream outMs = new MemoryStream())
479 {
480 using (ZOutputStream zOut = new ZOutputStream(outMs))
481 {
482 byte[] readBuffer = new byte[4096];
483 int readLen = 0;
484 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
485 {
486 zOut.Write(readBuffer, 0, readLen);
487 }
488 zOut.Flush();
489 outMs.Seek(0, SeekOrigin.Begin);
490
491 byte[] decompressedBuf = outMs.GetBuffer();
492 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
493 }
494 }
495 }
496 }
497 catch (Exception e)
498 {
499 return false;
500 }
501
502 OSDArray decodedMeshOsdArray = null;
503 if ((!decodedMeshOsd is OSDArray))
504 return false;
505
506 byte[] dummy;
507
508 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
509 foreach (OSD subMeshOsd in decodedMeshOsdArray)
510 {
511 if (subMeshOsd is OSDMap)
512 {
513 OSDMap subtmpmap = (OSDMap)subMeshOsd;
514 if (subtmpmap.ContainsKey("NoGeometry") && ((OSDBoolean)subtmpmap["NoGeometry"]))
515 continue;
516
517 if (!subtmpmap.ContainsKey("Position"))
518 return false;
519
520 if (subtmpmap.ContainsKey("TriangleList"))
521 {
522 dummy = subtmpmap["TriangleList"].AsBinary();
523 ntriangles += dummy.Length / bytesPerCoord;
524 }
525 else
526 return false;
527 }
528 }
529
530 return true;
531 }
532
533 // parses convex hulls component
534 private bool hulls(byte[] data, int offset, int size, out int nvertices, out int nhulls)
535 {
536 nvertices = 0;
537 nhulls = 1;
538
539 OSD decodedMeshOsd = new OSD();
540 byte[] meshBytes = new byte[size];
541 System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
542 try
543 {
544 using (MemoryStream inMs = new MemoryStream(meshBytes))
545 {
546 using (MemoryStream outMs = new MemoryStream())
547 {
548 using (ZOutputStream zOut = new ZOutputStream(outMs))
549 {
550 byte[] readBuffer = new byte[4096];
551 int readLen = 0;
552 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
553 {
554 zOut.Write(readBuffer, 0, readLen);
555 }
556 zOut.Flush();
557 outMs.Seek(0, SeekOrigin.Begin);
558
559 byte[] decompressedBuf = outMs.GetBuffer();
560 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
561 }
562 }
563 }
564 }
565 catch (Exception e)
566 {
567 return false;
568 }
569
570 OSDMap cmap = (OSDMap)decodedMeshOsd;
571 if (cmap == null)
572 return false;
573
574 byte[] dummy;
575
576 // must have one of this
577 if (cmap.ContainsKey("BoundingVerts"))
578 {
579 dummy = cmap["BoundingVerts"].AsBinary();
580 nvertices = dummy.Length / bytesPerCoord;
581 }
582 else
583 return false;
584
585/* upload is done with convex shape type
586 if (cmap.ContainsKey("HullList"))
587 {
588 dummy = cmap["HullList"].AsBinary();
589 nhulls += dummy.Length;
590 }
591
592
593 if (cmap.ContainsKey("Positions"))
594 {
595 dummy = cmap["Positions"].AsBinary();
596 nvertices = dummy.Length / bytesPerCoord;
597 }
598 */
599
600 return true;
601 }
602
603 // returns streaming cost from on mesh LODs sizes in curCost and square of prim size length
604 private float streamingCost(ameshCostParam curCost, float sqdiam)
605 {
606 // compute efective areas
607 float ma = 262144f;
608
609 float mh = sqdiam * highLodFactor;
610 if (mh > ma)
611 mh = ma;
612 float mm = sqdiam * midLodFactor;
613 if (mm > ma)
614 mm = ma;
615
616 float ml = sqdiam * lowLodFactor;
617 if (ml > ma)
618 ml = ma;
619
620 float mlst = ma;
621
622 mlst -= ml;
623 ml -= mm;
624 mm -= mh;
625
626 if (mlst < 1.0f)
627 mlst = 1.0f;
628 if (ml < 1.0f)
629 ml = 1.0f;
630 if (mm < 1.0f)
631 mm = 1.0f;
632 if (mh < 1.0f)
633 mh = 1.0f;
634
635 ma = mlst + ml + mm + mh;
636
637 // get LODs compressed sizes
638 // giving 384 bytes bonus
639 int lst = curCost.lowestLODSize - 384;
640 int l = curCost.lowLODSize - 384;
641 int m = curCost.medLODSize - 384;
642 int h = curCost.highLODSize - 384;
643
644 // use previus higher LOD size on missing ones
645 if (m <= 0)
646 m = h;
647 if (l <= 0)
648 l = m;
649 if (lst <= 0)
650 lst = l;
651
652 // force minumum sizes
653 if (lst < 16)
654 lst = 16;
655 if (l < 16)
656 l = 16;
657 if (m < 16)
658 m = 16;
659 if (h < 16)
660 h = 16;
661
662 // compute cost weighted by relative effective areas
663 float cost = (float)lst * mlst + (float)l * ml + (float)m * mm + (float)h * mh;
664 cost /= ma;
665
666 cost *= 0.004f; // overall tunning parameter
667
668 return cost;
669 }
670 }
671}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index ebfe687..e113c60 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -419,7 +419,7 @@ namespace OpenSim.Region.ClientStack.Linden
419 } 419 }
420 } 420 }
421 421
422 public Hashtable GetEvents(UUID requestID, UUID pAgentId, string request) 422 public Hashtable GetEvents(UUID requestID, UUID pAgentId)
423 { 423 {
424 if (DebugLevel >= 2) 424 if (DebugLevel >= 2)
425 m_log.DebugFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName); 425 m_log.DebugFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
index 5b125ea..cc65981 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
@@ -53,6 +53,14 @@ namespace OpenSim.Region.ClientStack.Linden
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")] 53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")]
54 public class GetTextureModule : INonSharedRegionModule 54 public class GetTextureModule : INonSharedRegionModule
55 { 55 {
56
57 struct aPollRequest
58 {
59 public PollServiceTextureEventArgs thepoll;
60 public UUID reqID;
61 public Hashtable request;
62 }
63
56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 64 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57 65
58 private Scene m_scene; 66 private Scene m_scene;
@@ -64,8 +72,8 @@ namespace OpenSim.Region.ClientStack.Linden
64 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>(); 72 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
65 private static Thread[] m_workerThreads = null; 73 private static Thread[] m_workerThreads = null;
66 74
67 private static OpenMetaverse.BlockingQueue<PollServiceTextureEventArgs> m_queue = 75 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
68 new OpenMetaverse.BlockingQueue<PollServiceTextureEventArgs>(); 76 new OpenMetaverse.BlockingQueue<aPollRequest>();
69 77
70 #region ISharedRegionModule Members 78 #region ISharedRegionModule Members
71 79
@@ -104,7 +112,7 @@ namespace OpenSim.Region.ClientStack.Linden
104 String.Format("TextureWorkerThread{0}", i), 112 String.Format("TextureWorkerThread{0}", i),
105 ThreadPriority.Normal, 113 ThreadPriority.Normal,
106 false, 114 false,
107 true, 115 false,
108 null, 116 null,
109 int.MaxValue); 117 int.MaxValue);
110 } 118 }
@@ -129,7 +137,8 @@ namespace OpenSim.Region.ClientStack.Linden
129 ~GetTextureModule() 137 ~GetTextureModule()
130 { 138 {
131 foreach (Thread t in m_workerThreads) 139 foreach (Thread t in m_workerThreads)
132 t.Abort(); 140 Watchdog.AbortThread(t.ManagedThreadId);
141
133 } 142 }
134 143
135 private class PollServiceTextureEventArgs : PollServiceEventArgs 144 private class PollServiceTextureEventArgs : PollServiceEventArgs
@@ -142,40 +151,50 @@ namespace OpenSim.Region.ClientStack.Linden
142 private Scene m_scene; 151 private Scene m_scene;
143 152
144 public PollServiceTextureEventArgs(UUID pId, Scene scene) : 153 public PollServiceTextureEventArgs(UUID pId, Scene scene) :
145 base(null, null, null, null, pId, 30000) 154 base(null, null, null, null, pId, int.MaxValue)
146 { 155 {
147 m_scene = scene; 156 m_scene = scene;
148 157
149 HasEvents = (x, y) => { return this.responses.ContainsKey(x); }; 158 HasEvents = (x, y) =>
150 GetEvents = (x, y, s) =>
151 { 159 {
152 try 160 lock (responses)
153 { 161 return responses.ContainsKey(x);
154 return this.responses[x]; 162 };
155 } 163 GetEvents = (x, y) =>
156 finally 164 {
165 lock (responses)
157 { 166 {
158 responses.Remove(x); 167 try
168 {
169 return responses[x];
170 }
171 finally
172 {
173 responses.Remove(x);
174 }
159 } 175 }
160 }; 176 };
161 177
162 Request = (x, y) => 178 Request = (x, y) =>
163 { 179 {
164 y["RequestID"] = x.ToString(); 180 aPollRequest reqinfo = new aPollRequest();
165 lock (this.requests) 181 reqinfo.thepoll = this;
166 this.requests.Add(y); 182 reqinfo.reqID = x;
183 reqinfo.request = y;
167 184
168 m_queue.Enqueue(this); 185 m_queue.Enqueue(reqinfo);
169 }; 186 };
170 187
188 // this should never happen except possible on shutdown
171 NoEvents = (x, y) => 189 NoEvents = (x, y) =>
172 { 190 {
173 lock (this.requests) 191/*
192 lock (requests)
174 { 193 {
175 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString()); 194 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
176 requests.Remove(request); 195 requests.Remove(request);
177 } 196 }
178 197*/
179 Hashtable response = new Hashtable(); 198 Hashtable response = new Hashtable();
180 199
181 response["int_response_code"] = 500; 200 response["int_response_code"] = 500;
@@ -188,25 +207,11 @@ namespace OpenSim.Region.ClientStack.Linden
188 }; 207 };
189 } 208 }
190 209
191 public void Process() 210 public void Process(aPollRequest requestinfo)
192 { 211 {
193 Hashtable response; 212 Hashtable response;
194 Hashtable request = null;
195 213
196 try 214 UUID requestID = requestinfo.reqID;
197 {
198 lock (this.requests)
199 {
200 request = requests[0];
201 requests.RemoveAt(0);
202 }
203 }
204 catch
205 {
206 return;
207 }
208
209 UUID requestID = new UUID(request["RequestID"].ToString());
210 215
211 // If the avatar is gone, don't bother to get the texture 216 // If the avatar is gone, don't bother to get the texture
212 if (m_scene.GetScenePresence(Id) == null) 217 if (m_scene.GetScenePresence(Id) == null)
@@ -219,13 +224,15 @@ namespace OpenSim.Region.ClientStack.Linden
219 response["keepalive"] = false; 224 response["keepalive"] = false;
220 response["reusecontext"] = false; 225 response["reusecontext"] = false;
221 226
222 responses[requestID] = response; 227 lock (responses)
228 responses[requestID] = response;
229
223 return; 230 return;
224 } 231 }
225 232
226 response = m_getTextureHandler.Handle(request); 233 response = m_getTextureHandler.Handle(requestinfo.request);
227 234 lock (responses)
228 responses[requestID] = response; 235 responses[requestID] = response;
229 } 236 }
230 } 237 }
231 238
@@ -233,8 +240,7 @@ namespace OpenSim.Region.ClientStack.Linden
233 { 240 {
234 string capUrl = "/CAPS/" + UUID.Random() + "/"; 241 string capUrl = "/CAPS/" + UUID.Random() + "/";
235 242
236 // Register this as a poll service 243 // Register this as a poll service
237 // absurd large timeout to tune later to make a bit less than viewer
238 PollServiceTextureEventArgs args = new PollServiceTextureEventArgs(agentID, m_scene); 244 PollServiceTextureEventArgs args = new PollServiceTextureEventArgs(agentID, m_scene);
239 245
240 args.Type = PollServiceEventArgs.EventType.Texture; 246 args.Type = PollServiceEventArgs.EventType.Texture;
@@ -270,11 +276,10 @@ namespace OpenSim.Region.ClientStack.Linden
270 { 276 {
271 while (true) 277 while (true)
272 { 278 {
273 PollServiceTextureEventArgs args = m_queue.Dequeue(); 279 aPollRequest poolreq = m_queue.Dequeue();
274 280
275 args.Process(); 281 poolreq.thepoll.Process(poolreq);
276 } 282 }
277 } 283 }
278 } 284 }
279
280} 285}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
index 44a6883..0251ac4 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
@@ -129,15 +129,15 @@ namespace OpenSim.Region.ClientStack.Linden
129// m_log.DebugFormat("[MESH UPLOAD FLAG MODULE]: MeshUploadFlag request"); 129// m_log.DebugFormat("[MESH UPLOAD FLAG MODULE]: MeshUploadFlag request");
130 130
131 OSDMap data = new OSDMap(); 131 OSDMap data = new OSDMap();
132 ScenePresence sp = m_scene.GetScenePresence(m_agentID); 132// ScenePresence sp = m_scene.GetScenePresence(m_agentID);
133 data["username"] = sp.Firstname + "." + sp.Lastname; 133// data["username"] = sp.Firstname + "." + sp.Lastname;
134 data["display_name_next_update"] = new OSDDate(DateTime.Now); 134// data["display_name_next_update"] = new OSDDate(DateTime.Now);
135 data["legacy_first_name"] = sp.Firstname; 135// data["legacy_first_name"] = sp.Firstname;
136 data["mesh_upload_status"] = "valid"; 136 data["mesh_upload_status"] = "valid";
137 data["display_name"] = sp.Firstname + " " + sp.Lastname; 137// data["display_name"] = sp.Firstname + " " + sp.Lastname;
138 data["legacy_last_name"] = sp.Lastname; 138// data["legacy_last_name"] = sp.Lastname;
139 data["id"] = m_agentID; 139// data["id"] = m_agentID;
140 data["is_display_name_default"] = true; 140// data["is_display_name_default"] = true;
141 141
142 //Send back data 142 //Send back data
143 Hashtable responsedata = new Hashtable(); 143 Hashtable responsedata = new Hashtable();
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 4908c2c..0caeddf 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -52,6 +52,13 @@ namespace OpenSim.Region.ClientStack.Linden
52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
53 public class WebFetchInvDescModule : INonSharedRegionModule 53 public class WebFetchInvDescModule : INonSharedRegionModule
54 { 54 {
55 struct aPollRequest
56 {
57 public PollServiceInventoryEventArgs thepoll;
58 public UUID reqID;
59 public Hashtable request;
60 }
61
55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 62 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56 63
57 private Scene m_scene; 64 private Scene m_scene;
@@ -64,8 +71,8 @@ namespace OpenSim.Region.ClientStack.Linden
64 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>(); 71 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
65 private static Thread[] m_workerThreads = null; 72 private static Thread[] m_workerThreads = null;
66 73
67 private static OpenMetaverse.BlockingQueue<PollServiceInventoryEventArgs> m_queue = 74 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
68 new OpenMetaverse.BlockingQueue<PollServiceInventoryEventArgs>(); 75 new OpenMetaverse.BlockingQueue<aPollRequest>();
69 76
70 #region ISharedRegionModule Members 77 #region ISharedRegionModule Members
71 78
@@ -131,49 +138,52 @@ namespace OpenSim.Region.ClientStack.Linden
131 ~WebFetchInvDescModule() 138 ~WebFetchInvDescModule()
132 { 139 {
133 foreach (Thread t in m_workerThreads) 140 foreach (Thread t in m_workerThreads)
134 t.Abort(); 141 Watchdog.AbortThread(t.ManagedThreadId);
135 } 142 }
136 143
137 private class PollServiceInventoryEventArgs : PollServiceEventArgs 144 private class PollServiceInventoryEventArgs : PollServiceEventArgs
138 { 145 {
139 private List<Hashtable> requests =
140 new List<Hashtable>();
141 private Dictionary<UUID, Hashtable> responses = 146 private Dictionary<UUID, Hashtable> responses =
142 new Dictionary<UUID, Hashtable>(); 147 new Dictionary<UUID, Hashtable>();
143 148
144 public PollServiceInventoryEventArgs(UUID pId) : 149 public PollServiceInventoryEventArgs(UUID pId) :
145 base(null, null, null, null, pId, 30000) 150 base(null, null, null, null, pId, int.MaxValue)
146 { 151 {
147 HasEvents = (x, y) => { return this.responses.ContainsKey(x); }; 152 HasEvents = (x, y) => { lock (responses) return responses.ContainsKey(x); };
148 GetEvents = (x, y, s) => 153 GetEvents = (x, y) =>
149 { 154 {
150 try 155 lock (responses)
151 {
152 return this.responses[x];
153 }
154 finally
155 { 156 {
156 responses.Remove(x); 157 try
158 {
159 return responses[x];
160 }
161 finally
162 {
163 responses.Remove(x);
164 }
157 } 165 }
158 }; 166 };
159 167
160 Request = (x, y) => 168 Request = (x, y) =>
161 { 169 {
162 y["RequestID"] = x.ToString(); 170 aPollRequest reqinfo = new aPollRequest();
163 lock (this.requests) 171 reqinfo.thepoll = this;
164 this.requests.Add(y); 172 reqinfo.reqID = x;
173 reqinfo.request = y;
165 174
166 m_queue.Enqueue(this); 175 m_queue.Enqueue(reqinfo);
167 }; 176 };
168 177
169 NoEvents = (x, y) => 178 NoEvents = (x, y) =>
170 { 179 {
171 lock (this.requests) 180/*
181 lock (requests)
172 { 182 {
173 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString()); 183 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
174 requests.Remove(request); 184 requests.Remove(request);
175 } 185 }
176 186*/
177 Hashtable response = new Hashtable(); 187 Hashtable response = new Hashtable();
178 188
179 response["int_response_code"] = 500; 189 response["int_response_code"] = 500;
@@ -186,24 +196,9 @@ namespace OpenSim.Region.ClientStack.Linden
186 }; 196 };
187 } 197 }
188 198
189 public void Process() 199 public void Process(aPollRequest requestinfo)
190 { 200 {
191 Hashtable request = null; 201 UUID requestID = requestinfo.reqID;
192
193 try
194 {
195 lock (this.requests)
196 {
197 request = requests[0];
198 requests.RemoveAt(0);
199 }
200 }
201 catch
202 {
203 return;
204 }
205
206 UUID requestID = new UUID(request["RequestID"].ToString());
207 202
208 Hashtable response = new Hashtable(); 203 Hashtable response = new Hashtable();
209 204
@@ -212,9 +207,11 @@ namespace OpenSim.Region.ClientStack.Linden
212 response["keepalive"] = false; 207 response["keepalive"] = false;
213 response["reusecontext"] = false; 208 response["reusecontext"] = false;
214 209
215 response["str_response_string"] = m_webFetchHandler.FetchInventoryDescendentsRequest(request["body"].ToString(), String.Empty, String.Empty, null, null); 210 response["str_response_string"] = m_webFetchHandler.FetchInventoryDescendentsRequest(
211 requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null);
216 212
217 responses[requestID] = response; 213 lock (responses)
214 responses[requestID] = response;
218 } 215 }
219 } 216 }
220 217
@@ -222,8 +219,7 @@ namespace OpenSim.Region.ClientStack.Linden
222 { 219 {
223 string capUrl = "/CAPS/" + UUID.Random() + "/"; 220 string capUrl = "/CAPS/" + UUID.Random() + "/";
224 221
225 // Register this as a poll service 222 // Register this as a poll service
226 // absurd large timeout to tune later to make a bit less than viewer
227 PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(agentID); 223 PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(agentID);
228 224
229 args.Type = PollServiceEventArgs.EventType.Inventory; 225 args.Type = PollServiceEventArgs.EventType.Inventory;
@@ -259,9 +255,9 @@ namespace OpenSim.Region.ClientStack.Linden
259 { 255 {
260 while (true) 256 while (true)
261 { 257 {
262 PollServiceInventoryEventArgs args = m_queue.Dequeue(); 258 aPollRequest poolreq = m_queue.Dequeue();
263 259
264 args.Process(); 260 poolreq.thepoll.Process(poolreq);
265 } 261 }
266 } 262 }
267 } 263 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 74b27d7..6f00957 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -2066,9 +2066,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2066 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset); 2066 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
2067 } 2067 }
2068 2068
2069 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2070 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId) 2069 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
2071 { 2070 {
2071 SendInventoryItemCreateUpdate(Item, UUID.Zero, callbackId);
2072 }
2073
2074 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2075 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
2076 {
2072 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; 2077 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
2073 2078
2074 UpdateCreateInventoryItemPacket InventoryReply 2079 UpdateCreateInventoryItemPacket InventoryReply
@@ -2078,6 +2083,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2078 // TODO: don't create new blocks if recycling an old packet 2083 // TODO: don't create new blocks if recycling an old packet
2079 InventoryReply.AgentData.AgentID = AgentId; 2084 InventoryReply.AgentData.AgentID = AgentId;
2080 InventoryReply.AgentData.SimApproved = true; 2085 InventoryReply.AgentData.SimApproved = true;
2086 InventoryReply.AgentData.TransactionID = transactionID;
2081 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1]; 2087 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1];
2082 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock(); 2088 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock();
2083 InventoryReply.InventoryData[0].ItemID = Item.ID; 2089 InventoryReply.InventoryData[0].ItemID = Item.ID;
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index 0271738..da1ff2e 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -143,7 +143,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
143 } 143 }
144 } 144 }
145 145
146 public void RequestCreateInventoryItem(IClientAPI remoteClient, 146 public bool RequestCreateInventoryItem(IClientAPI remoteClient,
147 UUID transactionID, UUID folderID, uint callbackID, 147 UUID transactionID, UUID folderID, uint callbackID,
148 string description, string name, sbyte invType, 148 string description, string name, sbyte invType,
149 sbyte type, byte wearableType, uint nextOwnerMask) 149 sbyte type, byte wearableType, uint nextOwnerMask)
@@ -153,6 +153,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
153 uploader.RequestCreateInventoryItem( 153 uploader.RequestCreateInventoryItem(
154 remoteClient, folderID, callbackID, 154 remoteClient, folderID, callbackID,
155 description, name, invType, type, wearableType, nextOwnerMask); 155 description, name, invType, type, wearableType, nextOwnerMask);
156
157 return true;
156 } 158 }
157 159
158 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, 160 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient,
@@ -172,4 +174,4 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
172 uploader.RequestUpdateInventoryItem(remoteClient, item); 174 uploader.RequestUpdateInventoryItem(remoteClient, item);
173 } 175 }
174 } 176 }
175} \ No newline at end of file 177}
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
index 73d1f72..4bb8986 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
@@ -158,7 +158,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
158 /// <param name="type"></param> 158 /// <param name="type"></param>
159 /// <param name="wearableType"></param> 159 /// <param name="wearableType"></param>
160 /// <param name="nextOwnerMask"></param> 160 /// <param name="nextOwnerMask"></param>
161 public void HandleItemCreationFromTransaction(IClientAPI remoteClient, 161 public bool HandleItemCreationFromTransaction(IClientAPI remoteClient,
162 UUID transactionID, UUID folderID, uint callbackID, 162 UUID transactionID, UUID folderID, uint callbackID,
163 string description, string name, sbyte invType, 163 string description, string name, sbyte invType,
164 sbyte type, byte wearableType, uint nextOwnerMask) 164 sbyte type, byte wearableType, uint nextOwnerMask)
@@ -169,7 +169,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
169 AgentAssetTransactions transactions = 169 AgentAssetTransactions transactions =
170 GetUserTransactions(remoteClient.AgentId); 170 GetUserTransactions(remoteClient.AgentId);
171 171
172 transactions.RequestCreateInventoryItem(remoteClient, transactionID, 172 return transactions.RequestCreateInventoryItem(remoteClient, transactionID,
173 folderID, callbackID, description, name, invType, type, 173 folderID, callbackID, description, name, invType, type,
174 wearableType, nextOwnerMask); 174 wearableType, nextOwnerMask);
175 } 175 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 1492302..716cc69 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -256,7 +256,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
256 if (sp.IsChildAgent) 256 if (sp.IsChildAgent)
257 return; 257 return;
258 sp.ControllingClient.Kick(reason); 258 sp.ControllingClient.Kick(reason);
259 sp.Scene.IncomingCloseAgent(sp.UUID); 259 sp.MakeChildAgent();
260 sp.ControllingClient.Close();
260 } 261 }
261 262
262 private void OnIncomingInstantMessage(GridInstantMessage msg) 263 private void OnIncomingInstantMessage(GridInstantMessage msg)
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 1f62743..c5bb9a5 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -663,7 +663,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
663 // 663 //
664 // This sleep can be increased if necessary. However, whilst it's active, 664 // This sleep can be increased if necessary. However, whilst it's active,
665 // an agent cannot teleport back to this region if it has teleported away. 665 // an agent cannot teleport back to this region if it has teleported away.
666 Thread.Sleep(2000); 666 Thread.Sleep(3000);
667 667
668 sp.Scene.IncomingCloseAgent(sp.UUID, false); 668 sp.Scene.IncomingCloseAgent(sp.UUID, false);
669 } 669 }
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 9a56f42..50f5f68 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -186,44 +186,43 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
186 if (folder == null || folder.Owner != remoteClient.AgentId) 186 if (folder == null || folder.Owner != remoteClient.AgentId)
187 return; 187 return;
188 188
189 if (transactionID == UUID.Zero) 189 if (transactionID != UUID.Zero)
190 { 190 {
191 ScenePresence presence; 191 IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule;
192 if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence)) 192 if (agentTransactions != null)
193 { 193 {
194 byte[] data = null; 194 if (agentTransactions.HandleItemCreationFromTransaction(
195 remoteClient, transactionID, folderID, callbackID, description,
196 name, invType, assetType, wearableType, nextOwnerMask))
197 return;
198 }
199 }
195 200
196 if (invType == (sbyte)InventoryType.Landmark && presence != null) 201 ScenePresence presence;
197 { 202 if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence))
198 string suffix = string.Empty, prefix = string.Empty; 203 {
199 string strdata = GenerateLandmark(presence, out prefix, out suffix); 204 byte[] data = null;
200 data = Encoding.ASCII.GetBytes(strdata);
201 name = prefix + name;
202 description += suffix;
203 }
204 205
205 AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); 206 if (invType == (sbyte)InventoryType.Landmark && presence != null)
206 m_Scene.AssetService.Store(asset);
207 m_Scene.CreateNewInventoryItem(
208 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
209 name, description, 0, callbackID, asset, invType, nextOwnerMask, creationDate);
210 }
211 else
212 { 207 {
213 m_log.ErrorFormat( 208 string suffix = string.Empty, prefix = string.Empty;
214 "[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem", 209 string strdata = GenerateLandmark(presence, out prefix, out suffix);
215 remoteClient.AgentId); 210 data = Encoding.ASCII.GetBytes(strdata);
211 name = prefix + name;
212 description += suffix;
216 } 213 }
214
215 AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId);
216 m_Scene.AssetService.Store(asset);
217 m_Scene.CreateNewInventoryItem(
218 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
219 name, description, 0, callbackID, asset, invType, nextOwnerMask, creationDate,transactionID);
217 } 220 }
218 else 221 else
219 { 222 {
220 IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule; 223 m_log.ErrorFormat(
221 if (agentTransactions != null) 224 "[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem",
222 { 225 remoteClient.AgentId);
223 agentTransactions.HandleItemCreationFromTransaction(
224 remoteClient, transactionID, folderID, callbackID, description,
225 name, invType, assetType, wearableType, nextOwnerMask);
226 }
227 } 226 }
228 } 227 }
229 228
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 99ffbe7..0b9174f 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -461,7 +461,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
461 } 461 }
462 } 462 }
463 } 463 }
464 private Hashtable GetEvents(UUID requestID, UUID sessionID, string request) 464 private Hashtable GetEvents(UUID requestID, UUID sessionID)
465 { 465 {
466 UrlData url = null; 466 UrlData url = null;
467 RequestData requestData = null; 467 RequestData requestData = null;
diff --git a/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs b/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
index 0cc8fb6..e0aad2b 100644
--- a/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.Framework.Interfaces
36 void HandleItemUpdateFromTransaction(IClientAPI remoteClient, UUID transactionID, 36 void HandleItemUpdateFromTransaction(IClientAPI remoteClient, UUID transactionID,
37 InventoryItemBase item); 37 InventoryItemBase item);
38 38
39 void HandleItemCreationFromTransaction(IClientAPI remoteClient, UUID transactionID, UUID folderID, 39 bool HandleItemCreationFromTransaction(IClientAPI remoteClient, UUID transactionID, UUID folderID,
40 uint callbackID, string description, string name, sbyte invType, 40 uint callbackID, string description, string name, sbyte invType,
41 sbyte type, byte wearableType, uint nextOwnerMask); 41 sbyte type, byte wearableType, uint nextOwnerMask);
42 42
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 3d68081..35df85c 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -904,11 +904,22 @@ namespace OpenSim.Region.Framework.Scenes
904 public void CreateNewInventoryItem( 904 public void CreateNewInventoryItem(
905 IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, 905 IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
906 string name, string description, uint flags, uint callbackID, 906 string name, string description, uint flags, uint callbackID,
907 AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate) 907 AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate, UUID transationID)
908 { 908 {
909 CreateNewInventoryItem( 909 CreateNewInventoryItem(
910 remoteClient, creatorID, creatorData, folderID, name, description, flags, callbackID, asset, invType, 910 remoteClient, creatorID, creatorData, folderID, name, description, flags, callbackID, asset, invType,
911 (uint)PermissionMask.All, (uint)PermissionMask.All, 0, nextOwnerMask, 0, creationDate); 911 (uint)PermissionMask.All, (uint)PermissionMask.All, 0, nextOwnerMask, 0, creationDate, transationID);
912 }
913
914
915 private void CreateNewInventoryItem(
916 IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
917 string name, string description, uint flags, uint callbackID, AssetBase asset, sbyte invType,
918 uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate)
919 {
920 CreateNewInventoryItem(remoteClient, creatorID, creatorData, folderID,
921 name, description, flags, callbackID, asset, invType,
922 baseMask, currentMask, everyoneMask, nextOwnerMask, groupMask, creationDate, UUID.Zero);
912 } 923 }
913 924
914 /// <summary> 925 /// <summary>
@@ -933,7 +944,7 @@ namespace OpenSim.Region.Framework.Scenes
933 private void CreateNewInventoryItem( 944 private void CreateNewInventoryItem(
934 IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, 945 IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
935 string name, string description, uint flags, uint callbackID, AssetBase asset, sbyte invType, 946 string name, string description, uint flags, uint callbackID, AssetBase asset, sbyte invType,
936 uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate) 947 uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate,UUID transationID)
937 { 948 {
938 InventoryItemBase item = new InventoryItemBase(); 949 InventoryItemBase item = new InventoryItemBase();
939 item.Owner = remoteClient.AgentId; 950 item.Owner = remoteClient.AgentId;
@@ -956,7 +967,7 @@ namespace OpenSim.Region.Framework.Scenes
956 967
957 if (AddInventoryItem(item)) 968 if (AddInventoryItem(item))
958 { 969 {
959 remoteClient.SendInventoryItemCreateUpdate(item, callbackID); 970 remoteClient.SendInventoryItemCreateUpdate(item, transationID, callbackID);
960 } 971 }
961 else 972 else
962 { 973 {
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 129bf09..29c8eb1 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -4372,7 +4372,7 @@ namespace OpenSim.Region.Framework.Scenes
4372 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4372 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID);
4373 if (presence != null) 4373 if (presence != null)
4374 { 4374 {
4375 presence.ControllingClient.Close(true, force); 4375 presence.ControllingClient.Close(force, force);
4376 return true; 4376 return true;
4377 } 4377 }
4378 4378
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 44573eb..a31a9ea 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -2146,10 +2146,10 @@ namespace OpenSim.Region.Framework.Scenes
2146 { 2146 {
2147 if (asset != null) 2147 if (asset != null)
2148 SculptTextureCallback(asset); 2148 SculptTextureCallback(asset);
2149 else 2149// else
2150 m_log.WarnFormat( 2150// m_log.WarnFormat(
2151 "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data", 2151// "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
2152 Name, UUID, id); 2152// Name, UUID, id);
2153 } 2153 }
2154 2154
2155 /// <summary> 2155 /// <summary>
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 1660c45..f3382b2 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -1100,7 +1100,12 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1100 1100
1101 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId) 1101 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
1102 { 1102 {
1103 1103
1104 }
1105
1106 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
1107 {
1108
1104 } 1109 }
1105 1110
1106 public void SendRemoveInventoryItem(UUID itemID) 1111 public void SendRemoveInventoryItem(UUID itemID)
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 625342e..bb3748e 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -739,6 +739,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
739 { 739 {
740 } 740 }
741 741
742 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
743 {
744 }
745
742 public virtual void SendRemoveInventoryItem(UUID itemID) 746 public virtual void SendRemoveInventoryItem(UUID itemID)
743 { 747 {
744 } 748 }
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
index fbc6134..61d5a1d 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
@@ -902,7 +902,7 @@ namespace OpenSim.Region.Physics.OdePlugin
902 axis.X = (axis.X > 0) ? 1f : 0f; 902 axis.X = (axis.X > 0) ? 1f : 0f;
903 axis.Y = (axis.Y > 0) ? 1f : 0f; 903 axis.Y = (axis.Y > 0) ? 1f : 0f;
904 axis.Z = (axis.Z > 0) ? 1f : 0f; 904 axis.Z = (axis.Z > 0) ? 1f : 0f;
905 m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z); 905// m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
906 AddChange(changes.AngLock, axis); 906 AddChange(changes.AngLock, axis);
907 } 907 }
908 else 908 else
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 8d06d83..f0d378d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -10149,31 +10149,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10149 UUID key = new UUID(); 10149 UUID key = new UUID();
10150 if (UUID.TryParse(id, out key)) 10150 if (UUID.TryParse(id, out key))
10151 { 10151 {
10152 try 10152 // return total object mass
10153 { 10153 SceneObjectPart part = World.GetSceneObjectPart(key);
10154 /* 10154 if (part != null)
10155 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 10155 return part.ParentGroup.GetMass();
10156 if (obj != null)
10157 return (double)obj.GetMass();
10158 */
10159 // return total object mass
10160 SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
10161 if (obj != null)
10162 return obj.GetMass();
10163 10156
10164 // the object is null so the key is for an avatar 10157 // the object is null so the key is for an avatar
10165 ScenePresence avatar = World.GetScenePresence(key); 10158 ScenePresence avatar = World.GetScenePresence(key);
10166 if (avatar != null) 10159 if (avatar != null)
10167 if (avatar.IsChildAgent)
10168 // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
10169 // child agents have a mass of 1.0
10170 return 1;
10171 else
10172 return (double)avatar.GetMass();
10173 }
10174 catch (KeyNotFoundException)
10175 { 10160 {
10176 return 0; // The Object/Agent not in the region so just return zero 10161 if (avatar.IsChildAgent)
10162 {
10163 // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
10164 // child agents have a mass of 1.0
10165 return 1;
10166 }
10167 else
10168 {
10169 return (double)avatar.GetMass();
10170 }
10177 } 10171 }
10178 } 10172 }
10179 return 0; 10173 return 0;
diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
index d772c39..0bd8269 100644
--- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
+++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
@@ -443,7 +443,15 @@ namespace OpenSim.Server.Handlers.Simulation
443 // subclasses can override this 443 // subclasses can override this
444 protected virtual bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) 444 protected virtual bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason)
445 { 445 {
446 return m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason); 446 reason = String.Empty;
447
448 Util.FireAndForget(x =>
449 {
450 string r;
451 m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out r);
452 });
453
454 return true;
447 } 455 }
448 } 456 }
449 457
diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
index daf38bc..9d6d9ad 100644
--- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
@@ -27,6 +27,7 @@
27 27
28using log4net; 28using log4net;
29using System; 29using System;
30using System.Threading;
30using System.Collections.Generic; 31using System.Collections.Generic;
31using System.IO; 32using System.IO;
32using System.Reflection; 33using System.Reflection;
@@ -50,7 +51,7 @@ namespace OpenSim.Services.Connectors
50 private IImprovedAssetCache m_Cache = null; 51 private IImprovedAssetCache m_Cache = null;
51 private int m_retryCounter; 52 private int m_retryCounter;
52 private Dictionary<int, List<AssetBase>> m_retryQueue = new Dictionary<int, List<AssetBase>>(); 53 private Dictionary<int, List<AssetBase>> m_retryQueue = new Dictionary<int, List<AssetBase>>();
53 private Timer m_retryTimer; 54 private System.Timers.Timer m_retryTimer;
54 private delegate void AssetRetrievedEx(AssetBase asset); 55 private delegate void AssetRetrievedEx(AssetBase asset);
55 56
56 // Keeps track of concurrent requests for the same asset, so that it's only loaded once. 57 // Keeps track of concurrent requests for the same asset, so that it's only loaded once.
@@ -61,6 +62,8 @@ namespace OpenSim.Services.Connectors
61 62
62 private Dictionary<string, string> m_UriMap = new Dictionary<string, string>(); 63 private Dictionary<string, string> m_UriMap = new Dictionary<string, string>();
63 64
65 private Thread[] m_fetchThreads;
66
64 public AssetServicesConnector() 67 public AssetServicesConnector()
65 { 68 {
66 } 69 }
@@ -96,7 +99,7 @@ namespace OpenSim.Services.Connectors
96 } 99 }
97 100
98 101
99 m_retryTimer = new Timer(); 102 m_retryTimer = new System.Timers.Timer();
100 m_retryTimer.Elapsed += new ElapsedEventHandler(retryCheck); 103 m_retryTimer.Elapsed += new ElapsedEventHandler(retryCheck);
101 m_retryTimer.Interval = 60000; 104 m_retryTimer.Interval = 60000;
102 105
@@ -112,6 +115,14 @@ namespace OpenSim.Services.Connectors
112 m_UriMap[prefix] = groupHost; 115 m_UriMap[prefix] = groupHost;
113 //m_log.DebugFormat("[ASSET]: Using {0} for prefix {1}", groupHost, prefix); 116 //m_log.DebugFormat("[ASSET]: Using {0} for prefix {1}", groupHost, prefix);
114 } 117 }
118
119 m_fetchThreads = new Thread[2];
120
121 for (int i = 0 ; i < 2 ; i++)
122 {
123 m_fetchThreads[i] = new Thread(AssetRequestProcessor);
124 m_fetchThreads[i].Start();
125 }
115 } 126 }
116 127
117 private string MapServer(string id) 128 private string MapServer(string id)
@@ -261,37 +272,25 @@ namespace OpenSim.Services.Connectors
261 return null; 272 return null;
262 } 273 }
263 274
264 public bool Get(string id, Object sender, AssetRetrieved handler) 275 private class QueuedAssetRequest
265 { 276 {
266 string uri = MapServer(id) + "/assets/" + id; 277 public string uri;
267 278 public string id;
268 AssetBase asset = null; 279 }
269 if (m_Cache != null)
270 asset = m_Cache.Get(id);
271 280
272 if (asset == null || asset.Data == null || asset.Data.Length == 0) 281 private OpenMetaverse.BlockingQueue<QueuedAssetRequest> m_requestQueue =
273 { 282 new OpenMetaverse.BlockingQueue<QueuedAssetRequest>();
274 lock (m_AssetHandlers)
275 {
276 AssetRetrievedEx handlerEx = new AssetRetrievedEx(delegate(AssetBase _asset) { handler(id, sender, _asset); });
277 283
278// AssetRetrievedEx handlers; 284 private void AssetRequestProcessor()
279 List<AssetRetrievedEx> handlers; 285 {
280 if (m_AssetHandlers.TryGetValue(id, out handlers)) 286 QueuedAssetRequest r;
281 {
282 // Someone else is already loading this asset. It will notify our handler when done.
283// handlers += handlerEx;
284 handlers.Add(handlerEx);
285 return true;
286 }
287 287
288 // Load the asset ourselves 288 while (true)
289// handlers += handlerEx; 289 {
290 handlers = new List<AssetRetrievedEx>(); 290 r = m_requestQueue.Dequeue();
291 handlers.Add(handlerEx);
292 291
293 m_AssetHandlers.Add(id, handlers); 292 string uri = r.uri;
294 } 293 string id = r.id;
295 294
296 bool success = false; 295 bool success = false;
297 try 296 try
@@ -301,16 +300,7 @@ namespace OpenSim.Services.Connectors
301 { 300 {
302 if (m_Cache != null) 301 if (m_Cache != null)
303 m_Cache.Cache(a); 302 m_Cache.Cache(a);
304/*
305 AssetRetrievedEx handlers;
306 lock (m_AssetHandlers)
307 {
308 handlers = m_AssetHandlers[id];
309 m_AssetHandlers.Remove(id);
310 }
311 303
312 handlers.Invoke(a);
313*/
314 List<AssetRetrievedEx> handlers; 304 List<AssetRetrievedEx> handlers;
315 lock (m_AssetHandlers) 305 lock (m_AssetHandlers)
316 { 306 {
@@ -340,6 +330,46 @@ namespace OpenSim.Services.Connectors
340 } 330 }
341 } 331 }
342 } 332 }
333 }
334
335 public bool Get(string id, Object sender, AssetRetrieved handler)
336 {
337 string uri = MapServer(id) + "/assets/" + id;
338
339 AssetBase asset = null;
340 if (m_Cache != null)
341 asset = m_Cache.Get(id);
342
343 if (asset == null || asset.Data == null || asset.Data.Length == 0)
344 {
345 lock (m_AssetHandlers)
346 {
347 AssetRetrievedEx handlerEx = new AssetRetrievedEx(delegate(AssetBase _asset) { handler(id, sender, _asset); });
348
349// AssetRetrievedEx handlers;
350 List<AssetRetrievedEx> handlers;
351 if (m_AssetHandlers.TryGetValue(id, out handlers))
352 {
353 // Someone else is already loading this asset. It will notify our handler when done.
354// handlers += handlerEx;
355 handlers.Add(handlerEx);
356 return true;
357 }
358
359 // Load the asset ourselves
360// handlers += handlerEx;
361 handlers = new List<AssetRetrievedEx>();
362 handlers.Add(handlerEx);
363
364 m_AssetHandlers.Add(id, handlers);
365 }
366
367 QueuedAssetRequest request = new QueuedAssetRequest();
368 request.id = id;
369 request.uri = uri;
370
371 m_requestQueue.Enqueue(request);
372 }
343 else 373 else
344 { 374 {
345 handler(id, sender, asset); 375 handler(id, sender, asset);
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index 4e3bc67..87ca944 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -716,6 +716,10 @@ namespace OpenSim.Tests.Common.Mock
716 { 716 {
717 } 717 }
718 718
719 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
720 {
721 }
722
719 public virtual void SendRemoveInventoryItem(UUID itemID) 723 public virtual void SendRemoveInventoryItem(UUID itemID)
720 { 724 {
721 } 725 }