aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs79
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs9
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs92
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs8
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs7
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs7
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs26
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs29
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs272
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs9
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs18
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs18
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs3
-rw-r--r--bin/OpenSimDefaults.ini17
17 files changed, 410 insertions, 193 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 14c5d6c..1108863 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -3567,7 +3567,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3567 /// with any other updates that may be queued for the same entity. 3567 /// with any other updates that may be queued for the same entity.
3568 /// The original update time is used for the merged update. 3568 /// The original update time is used for the merged update.
3569 /// </summary> 3569 /// </summary>
3570 public void ResendPrimUpdate(EntityUpdate update) 3570 private void ResendPrimUpdate(EntityUpdate update)
3571 { 3571 {
3572 // If the update exists in priority queue, it will be updated. 3572 // If the update exists in priority queue, it will be updated.
3573 // If it does not exist then it will be added with the current (rather than its original) priority 3573 // If it does not exist then it will be added with the current (rather than its original) priority
@@ -3583,8 +3583,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3583 /// with any other updates that may be queued for the same entity. 3583 /// with any other updates that may be queued for the same entity.
3584 /// The original update time is used for the merged update. 3584 /// The original update time is used for the merged update.
3585 /// </summary> 3585 /// </summary>
3586 void ResendPrimUpdates(List<EntityUpdate> updates) 3586 private void ResendPrimUpdates(List<EntityUpdate> updates)
3587 { 3587 {
3588 // m_log.WarnFormat("[CLIENT] resending prim update {0}",updates[0].UpdateTime);
3589
3588 foreach (EntityUpdate update in updates) 3590 foreach (EntityUpdate update in updates)
3589 ResendPrimUpdate(update); 3591 ResendPrimUpdate(update);
3590 } 3592 }
@@ -4018,6 +4020,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4018 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false)); 4020 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false));
4019 } 4021 }
4020 4022
4023 private void ResendPropertyUpdate(ObjectPropertyUpdate update)
4024 {
4025 uint priority = 0;
4026 lock (m_entityProps.SyncRoot)
4027 m_entityProps.Enqueue(priority, update);
4028 }
4029
4030 private void ResendPropertyUpdates(List<ObjectPropertyUpdate> updates)
4031 {
4032 // m_log.WarnFormat("[CLIENT] resending object property {0}",updates[0].UpdateTime);
4033
4034 foreach (ObjectPropertyUpdate update in updates)
4035 ResendPropertyUpdate(update);
4036 }
4037
4021 public void SendObjectPropertiesReply(ISceneEntity entity) 4038 public void SendObjectPropertiesReply(ISceneEntity entity)
4022 { 4039 {
4023 uint priority = 0; // time based ordering only 4040 uint priority = 0; // time based ordering only
@@ -4033,6 +4050,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4033 OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks = 4050 OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks =
4034 new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>(); 4051 new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>();
4035 4052
4053 OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> familyUpdates =
4054 new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
4055
4056 OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>> propertyUpdates =
4057 new OpenSim.Framework.Lazy<List<ObjectPropertyUpdate>>();
4058
4036 IEntityUpdate iupdate; 4059 IEntityUpdate iupdate;
4037 Int32 timeinqueue; // this is just debugging code & can be dropped later 4060 Int32 timeinqueue; // this is just debugging code & can be dropped later
4038 4061
@@ -4051,6 +4074,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4051 SceneObjectPart sop = (SceneObjectPart)update.Entity; 4074 SceneObjectPart sop = (SceneObjectPart)update.Entity;
4052 ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags); 4075 ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags);
4053 objectFamilyBlocks.Value.Add(objPropDB); 4076 objectFamilyBlocks.Value.Add(objPropDB);
4077 familyUpdates.Value.Add(update);
4054 } 4078 }
4055 } 4079 }
4056 4080
@@ -4061,6 +4085,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4061 SceneObjectPart sop = (SceneObjectPart)update.Entity; 4085 SceneObjectPart sop = (SceneObjectPart)update.Entity;
4062 ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop); 4086 ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop);
4063 objectPropertiesBlocks.Value.Add(objPropDB); 4087 objectPropertiesBlocks.Value.Add(objPropDB);
4088 propertyUpdates.Value.Add(update);
4064 } 4089 }
4065 } 4090 }
4066 4091
@@ -4068,12 +4093,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4068 } 4093 }
4069 4094
4070 4095
4071 Int32 ppcnt = 0; 4096 // Int32 ppcnt = 0;
4072 Int32 pbcnt = 0; 4097 // Int32 pbcnt = 0;
4073 4098
4074 if (objectPropertiesBlocks.IsValueCreated) 4099 if (objectPropertiesBlocks.IsValueCreated)
4075 { 4100 {
4076 List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value; 4101 List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value;
4102 List<ObjectPropertyUpdate> updates = propertyUpdates.Value;
4077 4103
4078 ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); 4104 ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
4079 packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count]; 4105 packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count];
@@ -4081,28 +4107,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4081 packet.ObjectData[i] = blocks[i]; 4107 packet.ObjectData[i] = blocks[i];
4082 4108
4083 packet.Header.Zerocoded = true; 4109 packet.Header.Zerocoded = true;
4084 OutPacket(packet, ThrottleOutPacketType.Task, true);
4085 4110
4086 pbcnt += blocks.Count; 4111 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4087 ppcnt++; 4112 // of the object rather than the properties when the packet was created
4113 OutPacket(packet, ThrottleOutPacketType.Task, true,
4114 delegate()
4115 {
4116 ResendPropertyUpdates(updates);
4117 });
4118
4119 // pbcnt += blocks.Count;
4120 // ppcnt++;
4088 } 4121 }
4089 4122
4090 Int32 fpcnt = 0; 4123 // Int32 fpcnt = 0;
4091 Int32 fbcnt = 0; 4124 // Int32 fbcnt = 0;
4092 4125
4093 if (objectFamilyBlocks.IsValueCreated) 4126 if (objectFamilyBlocks.IsValueCreated)
4094 { 4127 {
4095 List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value; 4128 List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value;
4096 4129 List<ObjectPropertyUpdate> updates = familyUpdates.Value;
4097 // ObjectPropertiesFamilyPacket objPropFamilyPack = 4130
4098 // (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
4099 //
4100 // objPropFamilyPack.ObjectData = new ObjectPropertiesFamilyPacket.ObjectDataBlock[blocks.Count];
4101 // for (int i = 0; i < blocks.Count; i++)
4102 // objPropFamilyPack.ObjectData[i] = blocks[i];
4103 //
4104 // OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task, true);
4105
4106 // one packet per object block... uggh... 4131 // one packet per object block... uggh...
4107 for (int i = 0; i < blocks.Count; i++) 4132 for (int i = 0; i < blocks.Count; i++)
4108 { 4133 {
@@ -4111,10 +4136,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4111 4136
4112 packet.ObjectData = blocks[i]; 4137 packet.ObjectData = blocks[i];
4113 packet.Header.Zerocoded = true; 4138 packet.Header.Zerocoded = true;
4114 OutPacket(packet, ThrottleOutPacketType.Task);
4115 4139
4116 fpcnt++; 4140 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4117 fbcnt++; 4141 // of the object rather than the properties when the packet was created
4142 ObjectPropertyUpdate update = updates[i];
4143 OutPacket(packet, ThrottleOutPacketType.Task, true,
4144 delegate()
4145 {
4146 ResendPropertyUpdate(update);
4147 });
4148
4149 // fpcnt++;
4150 // fbcnt++;
4118 } 4151 }
4119 4152
4120 } 4153 }
@@ -4151,7 +4184,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4151 4184
4152 return block; 4185 return block;
4153 } 4186 }
4154 4187
4155 private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop) 4188 private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop)
4156 { 4189 {
4157 //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); 4190 //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 7be8a0a..20bfec8 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -135,7 +135,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
135 private int m_nextOnQueueEmpty = 1; 135 private int m_nextOnQueueEmpty = 1;
136 136
137 /// <summary>Throttle bucket for this agent's connection</summary> 137 /// <summary>Throttle bucket for this agent's connection</summary>
138 private readonly TokenBucket m_throttleClient; 138 private readonly AdaptiveTokenBucket m_throttleClient;
139 public AdaptiveTokenBucket FlowThrottle
140 {
141 get { return m_throttleClient; }
142 }
143
139 /// <summary>Throttle bucket for this agent's connection</summary> 144 /// <summary>Throttle bucket for this agent's connection</summary>
140 private readonly TokenBucket m_throttleCategory; 145 private readonly TokenBucket m_throttleCategory;
141 /// <summary>Throttle buckets for each packet category</summary> 146 /// <summary>Throttle buckets for each packet category</summary>
@@ -176,7 +181,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
176 m_maxRTO = maxRTO; 181 m_maxRTO = maxRTO;
177 182
178 // Create a token bucket throttle for this client that has the scene token bucket as a parent 183 // Create a token bucket throttle for this client that has the scene token bucket as a parent
179 m_throttleClient = new TokenBucket(parentThrottle, rates.TotalLimit); 184 m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.TotalLimit);
180 // Create a token bucket throttle for the total categary with the client bucket as a throttle 185 // Create a token bucket throttle for the total categary with the client bucket as a throttle
181 m_throttleCategory = new TokenBucket(m_throttleClient, rates.TotalLimit); 186 m_throttleCategory = new TokenBucket(m_throttleClient, rates.TotalLimit);
182 // Create an array of token buckets for this clients different throttle categories 187 // Create an array of token buckets for this clients different throttle categories
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
index 07b0a1d..4ee6d3a 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
@@ -48,31 +48,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
48 /// Number of ticks (ms) per quantum, drip rate and max burst 48 /// Number of ticks (ms) per quantum, drip rate and max burst
49 /// are defined over this interval. 49 /// are defined over this interval.
50 /// </summary> 50 /// </summary>
51 private const Int32 m_ticksPerQuantum = 1000; 51 protected const Int32 m_ticksPerQuantum = 1000;
52 52
53 /// <summary> 53 /// <summary>
54 /// This is the number of quantums worth of packets that can 54 /// This is the number of quantums worth of packets that can
55 /// be accommodated during a burst 55 /// be accommodated during a burst
56 /// </summary> 56 /// </summary>
57 private const Double m_quantumsPerBurst = 1.5; 57 protected const Double m_quantumsPerBurst = 1.5;
58 58
59 /// <summary> 59 /// <summary>
60 /// </summary> 60 /// </summary>
61 private const Int32 m_minimumDripRate = 1400; 61 protected const Int32 m_minimumDripRate = 1400;
62 62
63 /// <summary>Time of the last drip, in system ticks</summary> 63 /// <summary>Time of the last drip, in system ticks</summary>
64 private Int32 m_lastDrip; 64 protected Int32 m_lastDrip;
65 65
66 /// <summary> 66 /// <summary>
67 /// The number of bytes that can be sent at this moment. This is the 67 /// The number of bytes that can be sent at this moment. This is the
68 /// current number of tokens in the bucket 68 /// current number of tokens in the bucket
69 /// </summary> 69 /// </summary>
70 private Int64 m_tokenCount; 70 protected Int64 m_tokenCount;
71 71
72 /// <summary> 72 /// <summary>
73 /// Map of children buckets and their requested maximum burst rate 73 /// Map of children buckets and their requested maximum burst rate
74 /// </summary> 74 /// </summary>
75 private Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>(); 75 protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>();
76 76
77#region Properties 77#region Properties
78 78
@@ -81,7 +81,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
81 /// parent. The parent bucket will limit the aggregate bandwidth of all 81 /// parent. The parent bucket will limit the aggregate bandwidth of all
82 /// of its children buckets 82 /// of its children buckets
83 /// </summary> 83 /// </summary>
84 private TokenBucket m_parent; 84 protected TokenBucket m_parent;
85 public TokenBucket Parent 85 public TokenBucket Parent
86 { 86 {
87 get { return m_parent; } 87 get { return m_parent; }
@@ -93,7 +93,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
93 /// of tokens that can accumulate in the bucket at any one time. This 93 /// of tokens that can accumulate in the bucket at any one time. This
94 /// also sets the total request for leaf nodes 94 /// also sets the total request for leaf nodes
95 /// </summary> 95 /// </summary>
96 private Int64 m_burstRate; 96 protected Int64 m_burstRate;
97 public Int64 RequestedBurstRate 97 public Int64 RequestedBurstRate
98 { 98 {
99 get { return m_burstRate; } 99 get { return m_burstRate; }
@@ -118,8 +118,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
118 /// <remarks>Tokens are added to the bucket any time 118 /// <remarks>Tokens are added to the bucket any time
119 /// <seealso cref="RemoveTokens"/> is called, at the granularity of 119 /// <seealso cref="RemoveTokens"/> is called, at the granularity of
120 /// the system tick interval (typically around 15-22ms)</remarks> 120 /// the system tick interval (typically around 15-22ms)</remarks>
121 private Int64 m_dripRate; 121 protected Int64 m_dripRate;
122 public Int64 RequestedDripRate 122 public virtual Int64 RequestedDripRate
123 { 123 {
124 get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); } 124 get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); }
125 set { 125 set {
@@ -131,7 +131,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
131 } 131 }
132 } 132 }
133 133
134 public Int64 DripRate 134 public virtual Int64 DripRate
135 { 135 {
136 get { 136 get {
137 if (m_parent == null) 137 if (m_parent == null)
@@ -149,7 +149,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
149 /// The current total of the requested maximum burst rates of 149 /// The current total of the requested maximum burst rates of
150 /// this bucket's children buckets. 150 /// this bucket's children buckets.
151 /// </summary> 151 /// </summary>
152 private Int64 m_totalDripRequest; 152 protected Int64 m_totalDripRequest;
153 public Int64 TotalDripRequest 153 public Int64 TotalDripRequest
154 { 154 {
155 get { return m_totalDripRequest; } 155 get { return m_totalDripRequest; }
@@ -189,7 +189,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
189 /// hierarchy. However, if any of the parents is over-booked, then 189 /// hierarchy. However, if any of the parents is over-booked, then
190 /// the modifier will be less than 1. 190 /// the modifier will be less than 1.
191 /// </summary> 191 /// </summary>
192 private double DripRateModifier() 192 protected double DripRateModifier()
193 { 193 {
194 Int64 driprate = DripRate; 194 Int64 driprate = DripRate;
195 return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest; 195 return driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest;
@@ -197,7 +197,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
197 197
198 /// <summary> 198 /// <summary>
199 /// </summary> 199 /// </summary>
200 private double BurstRateModifier() 200 protected double BurstRateModifier()
201 { 201 {
202 // for now... burst rate is always m_quantumsPerBurst (constant) 202 // for now... burst rate is always m_quantumsPerBurst (constant)
203 // larger than drip rate so the ratio of burst requests is the 203 // larger than drip rate so the ratio of burst requests is the
@@ -268,7 +268,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
268 /// Deposit tokens into the bucket from a child bucket that did 268 /// Deposit tokens into the bucket from a child bucket that did
269 /// not use all of its available tokens 269 /// not use all of its available tokens
270 /// </summary> 270 /// </summary>
271 private void Deposit(Int64 count) 271 protected void Deposit(Int64 count)
272 { 272 {
273 m_tokenCount += count; 273 m_tokenCount += count;
274 274
@@ -285,7 +285,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
285 /// call to Drip 285 /// call to Drip
286 /// </summary> 286 /// </summary>
287 /// <returns>True if tokens were added to the bucket, otherwise false</returns> 287 /// <returns>True if tokens were added to the bucket, otherwise false</returns>
288 private void Drip() 288 protected void Drip()
289 { 289 {
290 // This should never happen... means we are a leaf node and were created 290 // This should never happen... means we are a leaf node and were created
291 // with no drip rate... 291 // with no drip rate...
@@ -310,4 +310,64 @@ namespace OpenSim.Region.ClientStack.LindenUDP
310 Deposit(deltaMS * DripRate / m_ticksPerQuantum); 310 Deposit(deltaMS * DripRate / m_ticksPerQuantum);
311 } 311 }
312 } 312 }
313
314 public class AdaptiveTokenBucket : TokenBucket
315 {
316 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
317
318 // <summary>
319 // The minimum rate for flow control.
320 // </summary>
321 protected const Int64 m_minimumFlow = m_minimumDripRate * 10;
322
323 // <summary>
324 // The maximum rate for flow control. Drip rate can never be
325 // greater than this.
326 // </summary>
327 protected Int64 m_maxDripRate = 0;
328 protected Int64 MaxDripRate
329 {
330 get { return (m_maxDripRate == 0 ? m_totalDripRequest : m_maxDripRate); }
331 set { m_maxDripRate = (value == 0 ? 0 : Math.Max(value,m_minimumFlow)); }
332 }
333
334 // <summary>
335 //
336 // </summary>
337 public virtual Int64 AdjustedDripRate
338 {
339 get { return m_dripRate; }
340 set {
341 m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value,m_minimumFlow,MaxDripRate);
342 m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst);
343 if (m_parent != null)
344 m_parent.RegisterRequest(this,m_dripRate);
345 }
346 }
347
348 // <summary>
349 //
350 // </summary>
351 public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate) : base(parent,m_minimumFlow)
352 {
353 MaxDripRate = maxDripRate;
354 }
355
356 // <summary>
357 //
358 // </summary>
359 public void ExpirePackets(Int32 count)
360 {
361 // m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count);
362 AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count));
363 }
364
365 // <summary>
366 //
367 // </summary>
368 public void AcknowledgePackets(Int32 count)
369 {
370 AdjustedDripRate = AdjustedDripRate + count;
371 }
372 }
313} 373}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
index d195110..b170964 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
@@ -130,6 +130,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
130 // is actually sent out again 130 // is actually sent out again
131 packet.TickCount = 0; 131 packet.TickCount = 0;
132 132
133 // As with other network applications, assume that an expired packet is
134 // an indication of some network problem, slow transmission
135 packet.Client.FlowThrottle.ExpirePackets(1);
136
133 expiredPackets.Add(packet); 137 expiredPackets.Add(packet);
134 } 138 }
135 } 139 }
@@ -157,6 +161,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
157 { 161 {
158 m_packets.Remove(pendingRemove.SequenceNumber); 162 m_packets.Remove(pendingRemove.SequenceNumber);
159 163
164 // As with other network applications, assume that an acknowledged packet is an
165 // indication that the network can handle a little more load, speed up the transmission
166 ackedPacket.Client.FlowThrottle.AcknowledgePackets(ackedPacket.Buffer.DataLength);
167
160 // Update stats 168 // Update stats
161 Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); 169 Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
162 170
diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs
index d2278bc..deec444 100644
--- a/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Assets/GetMeshModule.cs
@@ -66,12 +66,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets
66 66
67 public void Initialise(IConfigSource source) 67 public void Initialise(IConfigSource source)
68 { 68 {
69 IConfig startupConfig = source.Configs["Startup"]; 69 IConfig meshConfig = source.Configs["Mesh"];
70 if (startupConfig == null) 70 if (meshConfig == null)
71 return; 71 return;
72 72
73 if (!startupConfig.GetBoolean("ColladaMesh",true)) 73 m_enabled = meshConfig.GetBoolean("ColladaMesh", true);
74 m_enabled = false;
75 } 74 }
76 75
77 public void AddRegion(Scene pScene) 76 public void AddRegion(Scene pScene)
diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs
index fb07cc9..d651cb2 100644
--- a/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs
@@ -68,12 +68,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets
68 68
69 public void Initialise(IConfigSource source) 69 public void Initialise(IConfigSource source)
70 { 70 {
71 IConfig startupConfig = source.Configs["Startup"]; 71 IConfig meshConfig = source.Configs["Mesh"];
72 if (startupConfig == null) 72 if (meshConfig == null)
73 return; 73 return;
74 74
75 if (!startupConfig.GetBoolean("ColladaMesh",true)) 75 m_enabled = meshConfig.GetBoolean("ColladaMesh", true);
76 m_enabled = false;
77 } 76 }
78 77
79 public void AddRegion(Scene pScene) 78 public void AddRegion(Scene pScene)
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index f3d2f26..6b24718 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -78,11 +78,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
78 private Stream m_loadStream; 78 private Stream m_loadStream;
79 79
80 /// <summary> 80 /// <summary>
81 /// FIXME: Do not perform this check since older versions of OpenSim do save the control file after other things 81 /// Has the control file been loaded for this archive?
82 /// (I thought they weren't). We will need to bump the version number and perform this check on all
83 /// subsequent IAR versions only
84 /// </summary> 82 /// </summary>
85 protected bool m_controlFileLoaded = true; 83 public bool ControlFileLoaded { get; private set; }
84
85 /// <summary>
86 /// Do we want to enforce the check. IAR versions before 0.2 and 1.1 do not guarantee this order, so we can't
87 /// enforce.
88 /// </summary>
89 public bool EnforceControlFileCheck { get; private set; }
90
86 protected bool m_assetsLoaded; 91 protected bool m_assetsLoaded;
87 protected bool m_inventoryNodesLoaded; 92 protected bool m_inventoryNodesLoaded;
88 93
@@ -131,6 +136,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
131 m_userInfo = userInfo; 136 m_userInfo = userInfo;
132 m_invPath = invPath; 137 m_invPath = invPath;
133 m_loadStream = loadStream; 138 m_loadStream = loadStream;
139
140 // FIXME: Do not perform this check since older versions of OpenSim do save the control file after other things
141 // (I thought they weren't). We will need to bump the version number and perform this check on all
142 // subsequent IAR versions only
143 ControlFileLoaded = true;
134 } 144 }
135 145
136 /// <summary> 146 /// <summary>
@@ -522,7 +532,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
522 /// </summary> 532 /// </summary>
523 /// <param name="path"></param> 533 /// <param name="path"></param>
524 /// <param name="data"></param> 534 /// <param name="data"></param>
525 protected void LoadControlFile(string path, byte[] data) 535 public void LoadControlFile(string path, byte[] data)
526 { 536 {
527 XDocument doc = XDocument.Parse(Encoding.ASCII.GetString(data)); 537 XDocument doc = XDocument.Parse(Encoding.ASCII.GetString(data));
528 XElement archiveElement = doc.Element("archive"); 538 XElement archiveElement = doc.Element("archive");
@@ -538,7 +548,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
538 majorVersion, MAX_MAJOR_VERSION)); 548 majorVersion, MAX_MAJOR_VERSION));
539 } 549 }
540 550
541 m_controlFileLoaded = true; 551 ControlFileLoaded = true;
542 m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version); 552 m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version);
543 } 553 }
544 554
@@ -550,7 +560,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
550 /// <param name="data"></param> 560 /// <param name="data"></param>
551 protected void LoadInventoryFile(string path, TarArchiveReader.TarEntryType entryType, byte[] data) 561 protected void LoadInventoryFile(string path, TarArchiveReader.TarEntryType entryType, byte[] data)
552 { 562 {
553 if (!m_controlFileLoaded) 563 if (!ControlFileLoaded)
554 throw new Exception( 564 throw new Exception(
555 string.Format( 565 string.Format(
556 "The IAR you are trying to load does not list {0} before {1}. Aborting load", 566 "The IAR you are trying to load does not list {0} before {1}. Aborting load",
@@ -597,7 +607,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
597 /// <param name="data"></param> 607 /// <param name="data"></param>
598 protected void LoadAssetFile(string path, byte[] data) 608 protected void LoadAssetFile(string path, byte[] data)
599 { 609 {
600 if (!m_controlFileLoaded) 610 if (!ControlFileLoaded)
601 throw new Exception( 611 throw new Exception(
602 string.Format( 612 string.Format(
603 "The IAR you are trying to load does not list {0} before {1}. Aborting load", 613 "The IAR you are trying to load does not list {0} before {1}. Aborting load",
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index dc4900f..c039b5a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -394,12 +394,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
394 if (options.ContainsKey("profile")) 394 if (options.ContainsKey("profile"))
395 { 395 {
396 majorVersion = 1; 396 majorVersion = 1;
397 minorVersion = 0; 397 minorVersion = 1;
398 } 398 }
399 else 399 else
400 { 400 {
401 majorVersion = 0; 401 majorVersion = 0;
402 minorVersion = 1; 402 minorVersion = 2;
403 } 403 }
404 404
405 m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion); 405 m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
index d03f6da..52232a0 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
@@ -94,7 +94,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
94 94
95 Assert.That(coaObjects[1].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000140"))); 95 Assert.That(coaObjects[1].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000140")));
96 Assert.That(coaObjects[1].AbsolutePosition, Is.EqualTo(new Vector3(25, 50, 75))); 96 Assert.That(coaObjects[1].AbsolutePosition, Is.EqualTo(new Vector3(25, 50, 75)));
97 } 97 }
98
99 /// <summary>
100 /// Test that the IAR has the required files in the right order.
101 /// </summary>
102 /// <remarks>
103 /// At the moment, the only thing that matters is that the control file is the very first one.
104 /// </remarks>
105 [Test]
106 public void TestOrder()
107 {
108 TestHelper.InMethod();
109// log4net.Config.XmlConfigurator.Configure();
110
111 MemoryStream archiveReadStream = new MemoryStream(m_iarStreamBytes);
112 TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
113 string filePath;
114 TarArchiveReader.TarEntryType tarEntryType;
115
116 byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
117 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
118
119 InventoryArchiveReadRequest iarr
120 = new InventoryArchiveReadRequest(null, null, null, (Stream)null, false);
121 iarr.LoadControlFile(filePath, data);
122
123 Assert.That(iarr.ControlFileLoaded, Is.True);
124 }
98 125
99 /// <summary> 126 /// <summary>
100 /// Test saving a single inventory item to a V0.1 OpenSim Inventory Archive 127 /// Test saving a single inventory item to a V0.1 OpenSim Inventory Archive
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
index 8c99983..52791cb 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
@@ -75,6 +75,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
75 if (name == Name) 75 if (name == Name)
76 { 76 {
77 m_Enabled = true; 77 m_Enabled = true;
78
79 InitialiseCommon(source);
80
78 m_log.InfoFormat("[HG INVENTORY ACCESS MODULE]: {0} enabled.", Name); 81 m_log.InfoFormat("[HG INVENTORY ACCESS MODULE]: {0} enabled.", Name);
79 82
80 IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"]; 83 IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"];
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index a716326..6b3df9d 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -64,7 +64,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
64 return m_UserManagement; 64 return m_UserManagement;
65 } 65 }
66 } 66 }
67 67
68 public bool CoalesceMultipleObjectsToInventory { get; set; }
68 69
69 #region INonSharedRegionModule 70 #region INonSharedRegionModule
70 71
@@ -87,10 +88,28 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
87 if (name == Name) 88 if (name == Name)
88 { 89 {
89 m_Enabled = true; 90 m_Enabled = true;
90 m_log.InfoFormat("[INVENTORY ACCESS MODULE]: {0} enabled.", Name); 91
92 InitialiseCommon(source);
93
94 m_log.InfoFormat("[INVENTORY ACCESS MODULE]: {0} enabled.", Name);
91 } 95 }
92 } 96 }
93 } 97 }
98
99 /// <summary>
100 /// Common module config for both this and descendant classes.
101 /// </summary>
102 /// <param name="source"></param>
103 protected virtual void InitialiseCommon(IConfigSource source)
104 {
105 IConfig inventoryConfig = source.Configs["Inventory"];
106
107 if (inventoryConfig != null)
108 CoalesceMultipleObjectsToInventory
109 = inventoryConfig.GetBoolean("CoalesceMultipleObjectsToInventory", true);
110 else
111 CoalesceMultipleObjectsToInventory = true;
112 }
94 113
95 public virtual void PostInitialise() 114 public virtual void PostInitialise()
96 { 115 {
@@ -194,32 +213,34 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
194 213
195 return UUID.Zero; 214 return UUID.Zero;
196 } 215 }
197 216
198 /// <summary> 217 public virtual UUID CopyToInventory(DeRezAction action, UUID folderID,
199 /// Delete a scene object from a scene and place in the given avatar's inventory.
200 /// Returns the UUID of the newly created asset.
201 /// </summary>
202 /// <param name="action"></param>
203 /// <param name="folderID"></param>
204 /// <param name="objectGroup"></param>
205 /// <param name="remoteClient"> </param>
206 public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID,
207 List<SceneObjectGroup> objectGroups, IClientAPI remoteClient) 218 List<SceneObjectGroup> objectGroups, IClientAPI remoteClient)
208 { 219 {
209 UUID ret = UUID.Zero; 220 Dictionary<UUID, List<SceneObjectGroup>> bundlesToCopy = new Dictionary<UUID, List<SceneObjectGroup>>();
210 221
211 // The following code groups the SOG's by owner. No objects 222 if (CoalesceMultipleObjectsToInventory)
212 // belonging to different people can be coalesced, for obvious
213 // reasons.
214 Dictionary<UUID, List<SceneObjectGroup>> deletes =
215 new Dictionary<UUID, List<SceneObjectGroup>>();
216
217 foreach (SceneObjectGroup g in objectGroups)
218 { 223 {
219 if (!deletes.ContainsKey(g.OwnerID)) 224 // The following code groups the SOG's by owner. No objects
220 deletes[g.OwnerID] = new List<SceneObjectGroup>(); 225 // belonging to different people can be coalesced, for obvious
221 226 // reasons.
222 deletes[g.OwnerID].Add(g); 227 foreach (SceneObjectGroup g in objectGroups)
228 {
229 if (!bundlesToCopy.ContainsKey(g.OwnerID))
230 bundlesToCopy[g.OwnerID] = new List<SceneObjectGroup>();
231
232 bundlesToCopy[g.OwnerID].Add(g);
233 }
234 }
235 else
236 {
237 // If we don't want to coalesce then put every object in its own bundle.
238 foreach (SceneObjectGroup g in objectGroups)
239 {
240 List<SceneObjectGroup> bundle = new List<SceneObjectGroup>();
241 bundle.Add(g);
242 bundlesToCopy[g.UUID] = bundle;
243 }
223 } 244 }
224 245
225 // This is method scoped and will be returned. It will be the 246 // This is method scoped and will be returned. It will be the
@@ -228,112 +249,129 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
228 249
229 // Each iteration is really a separate asset being created, 250 // Each iteration is really a separate asset being created,
230 // with distinct destinations as well. 251 // with distinct destinations as well.
231 foreach (List<SceneObjectGroup> objlist in deletes.Values) 252 foreach (List<SceneObjectGroup> bundle in bundlesToCopy.Values)
253 assetID = CopyBundleToInventory(action, folderID, bundle, remoteClient);
254
255 return assetID;
256 }
257
258 /// <summary>
259 /// Copy a bundle of objects to inventory. If there is only one object, then this will create an object
260 /// item. If there are multiple objects then these will be saved as a single coalesced item.
261 /// </summary>
262 /// <param name="action"></param>
263 /// <param name="folderID"></param>
264 /// <param name="objlist"></param>
265 /// <param name="remoteClient"></param>
266 /// <returns></returns>
267 protected UUID CopyBundleToInventory(
268 DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient)
269 {
270 UUID assetID = UUID.Zero;
271
272 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
273 Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
274
275 foreach (SceneObjectGroup objectGroup in objlist)
232 { 276 {
233 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); 277 Vector3 inventoryStoredPosition = new Vector3
234 Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>(); 278 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
279 ? 250
280 : objectGroup.AbsolutePosition.X)
281 ,
282 (objectGroup.AbsolutePosition.Y > (int)Constants.RegionSize)
283 ? 250
284 : objectGroup.AbsolutePosition.Y,
285 objectGroup.AbsolutePosition.Z);
286
287 originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition;
288
289 objectGroup.AbsolutePosition = inventoryStoredPosition;
290
291 // Make sure all bits but the ones we want are clear
292 // on take.
293 // This will be applied to the current perms, so
294 // it will do what we want.
295 objectGroup.RootPart.NextOwnerMask &=
296 ((uint)PermissionMask.Copy |
297 (uint)PermissionMask.Transfer |
298 (uint)PermissionMask.Modify);
299 objectGroup.RootPart.NextOwnerMask |=
300 (uint)PermissionMask.Move;
301
302 coa.Add(objectGroup);
303 }
235 304
236 foreach (SceneObjectGroup objectGroup in objlist) 305 string itemXml;
237 {
238 Vector3 inventoryStoredPosition = new Vector3
239 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
240 ? 250
241 : objectGroup.AbsolutePosition.X)
242 ,
243 (objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
244 ? 250
245 : objectGroup.AbsolutePosition.X,
246 objectGroup.AbsolutePosition.Z);
247
248 originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition;
249
250 objectGroup.AbsolutePosition = inventoryStoredPosition;
251
252 // Make sure all bits but the ones we want are clear
253 // on take.
254 // This will be applied to the current perms, so
255 // it will do what we want.
256 objectGroup.RootPart.NextOwnerMask &=
257 ((uint)PermissionMask.Copy |
258 (uint)PermissionMask.Transfer |
259 (uint)PermissionMask.Modify);
260 objectGroup.RootPart.NextOwnerMask |=
261 (uint)PermissionMask.Move;
262
263 coa.Add(objectGroup);
264 }
265 306
266 string itemXml; 307 if (objlist.Count > 1)
308 itemXml = CoalescedSceneObjectsSerializer.ToXml(coa);
309 else
310 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0]);
311
312 // Restore the position of each group now that it has been stored to inventory.
313 foreach (SceneObjectGroup objectGroup in objlist)
314 objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
267 315
268 if (objlist.Count > 1) 316 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID);
269 itemXml = CoalescedSceneObjectsSerializer.ToXml(coa); 317 if (item == null)
270 else 318 return UUID.Zero;
271 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0]); 319
272 320 // Can't know creator is the same, so null it in inventory
273 // Restore the position of each group now that it has been stored to inventory. 321 if (objlist.Count > 1)
274 foreach (SceneObjectGroup objectGroup in objlist) 322 {
275 objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; 323 item.CreatorId = UUID.Zero.ToString();
324 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems;
325 }
326 else
327 {
328 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
329 item.SaleType = objlist[0].RootPart.ObjectSaleType;
330 item.SalePrice = objlist[0].RootPart.SalePrice;
331 }
332
333 AssetBase asset = CreateAsset(
334 objlist[0].GetPartName(objlist[0].RootPart.LocalId),
335 objlist[0].GetPartDescription(objlist[0].RootPart.LocalId),
336 (sbyte)AssetType.Object,
337 Utils.StringToBytes(itemXml),
338 objlist[0].OwnerID.ToString());
339 m_Scene.AssetService.Store(asset);
340
341 item.AssetID = asset.FullID;
342 assetID = asset.FullID;
276 343
277 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); 344 if (DeRezAction.SaveToExistingUserInventoryItem == action)
278 if (item == null) 345 {
279 return UUID.Zero; 346 m_Scene.InventoryService.UpdateItem(item);
280 347 }
281 // Can't know creator is the same, so null it in inventory 348 else
282 if (objlist.Count > 1) 349 {
283 { 350 AddPermissions(item, objlist[0], objlist, remoteClient);
284 item.CreatorId = UUID.Zero.ToString(); 351
285 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems; 352 item.CreationDate = Util.UnixTimeSinceEpoch();
286 } 353 item.Description = asset.Description;
287 else 354 item.Name = asset.Name;
288 { 355 item.AssetType = asset.Type;
289 item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); 356
290 item.SaleType = objlist[0].RootPart.ObjectSaleType; 357 m_Scene.AddInventoryItem(item);
291 item.SalePrice = objlist[0].RootPart.SalePrice;
292 }
293
294 AssetBase asset = CreateAsset(
295 objlist[0].GetPartName(objlist[0].RootPart.LocalId),
296 objlist[0].GetPartDescription(objlist[0].RootPart.LocalId),
297 (sbyte)AssetType.Object,
298 Utils.StringToBytes(itemXml),
299 objlist[0].OwnerID.ToString());
300 m_Scene.AssetService.Store(asset);
301
302 item.AssetID = asset.FullID;
303 assetID = asset.FullID;
304 358
305 if (DeRezAction.SaveToExistingUserInventoryItem == action) 359 if (remoteClient != null && item.Owner == remoteClient.AgentId)
306 { 360 {
307 m_Scene.InventoryService.UpdateItem(item); 361 remoteClient.SendInventoryItemCreateUpdate(item, 0);
308 } 362 }
309 else 363 else
310 { 364 {
311 AddPermissions(item, objlist[0], objlist, remoteClient); 365 ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner);
312 366 if (notifyUser != null)
313 item.CreationDate = Util.UnixTimeSinceEpoch();
314 item.Description = asset.Description;
315 item.Name = asset.Name;
316 item.AssetType = asset.Type;
317
318 m_Scene.AddInventoryItem(item);
319
320 if (remoteClient != null && item.Owner == remoteClient.AgentId)
321 {
322 remoteClient.SendInventoryItemCreateUpdate(item, 0);
323 }
324 else
325 { 367 {
326 ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner); 368 notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
327 if (notifyUser != null)
328 {
329 notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
330 }
331 } 369 }
332 } 370 }
333
334 // This is a hook to do some per-asset post-processing for subclasses that need that
335 ExportAsset(remoteClient.AgentId, assetID);
336 } 371 }
372
373 // This is a hook to do some per-asset post-processing for subclasses that need that
374 ExportAsset(remoteClient.AgentId, assetID);
337 375
338 return assetID; 376 return assetID;
339 } 377 }
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index fd8f546..82bef48 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -57,6 +57,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
57 /// bumps here should be compatible. 57 /// bumps here should be compatible.
58 /// </summary> 58 /// </summary>
59 public static int MAX_MAJOR_VERSION = 1; 59 public static int MAX_MAJOR_VERSION = 1;
60
61 /// <summary>
62 /// Has the control file been loaded for this archive?
63 /// </summary>
64 public bool ControlFileLoaded { get; private set; }
60 65
61 protected Scene m_scene; 66 protected Scene m_scene;
62 protected Stream m_loadStream; 67 protected Stream m_loadStream;
@@ -527,7 +532,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
527 /// </summary> 532 /// </summary>
528 /// <param name="path"></param> 533 /// <param name="path"></param>
529 /// <param name="data"></param> 534 /// <param name="data"></param>
530 protected void LoadControlFile(string path, byte[] data) 535 public void LoadControlFile(string path, byte[] data)
531 { 536 {
532 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); 537 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
533 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); 538 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
@@ -573,6 +578,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
573 } 578 }
574 579
575 currentRegionSettings.Save(); 580 currentRegionSettings.Save();
581
582 ControlFileLoaded = true;
576 } 583 }
577 } 584 }
578} \ No newline at end of file 585} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
index f2d487e..597b780 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
@@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
206 /// <returns></returns> 206 /// <returns></returns>
207 public static string CreateControlFile(Dictionary<string, object> options) 207 public static string CreateControlFile(Dictionary<string, object> options)
208 { 208 {
209 int majorVersion = MAX_MAJOR_VERSION, minorVersion = 5; 209 int majorVersion = MAX_MAJOR_VERSION, minorVersion = 6;
210// 210//
211// if (options.ContainsKey("version")) 211// if (options.ContainsKey("version"))
212// { 212// {
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
index e2760a2..2307c8e 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -171,7 +171,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
171 MemoryStream archiveReadStream = new MemoryStream(archive); 171 MemoryStream archiveReadStream = new MemoryStream(archive);
172 TarArchiveReader tar = new TarArchiveReader(archiveReadStream); 172 TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
173 173
174 bool gotControlFile = false;
175 bool gotNcAssetFile = false; 174 bool gotNcAssetFile = false;
176 175
177 string expectedNcAssetFileName = string.Format("{0}_{1}", ncAssetUuid, "notecard.txt"); 176 string expectedNcAssetFileName = string.Format("{0}_{1}", ncAssetUuid, "notecard.txt");
@@ -182,15 +181,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
182 expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2)); 181 expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2));
183 182
184 string filePath; 183 string filePath;
185 TarArchiveReader.TarEntryType tarEntryType; 184 TarArchiveReader.TarEntryType tarEntryType;
186 185
186 byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
187 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
188
189 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
190 arr.LoadControlFile(filePath, data);
191
192 Assert.That(arr.ControlFileLoaded, Is.True);
193
187 while (tar.ReadEntry(out filePath, out tarEntryType) != null) 194 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
188 { 195 {
189 if (ArchiveConstants.CONTROL_FILE_PATH == filePath) 196 if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
190 {
191 gotControlFile = true;
192 }
193 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
194 { 197 {
195 string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length); 198 string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
196 199
@@ -203,7 +206,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
203 } 206 }
204 } 207 }
205 208
206 Assert.That(gotControlFile, Is.True, "No control file in archive");
207 Assert.That(gotNcAssetFile, Is.True, "No notecard asset file in archive"); 209 Assert.That(gotNcAssetFile, Is.True, "No notecard asset file in archive");
208 Assert.That(foundPaths, Is.EquivalentTo(expectedPaths)); 210 Assert.That(foundPaths, Is.EquivalentTo(expectedPaths));
209 211
diff --git a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs
index 05fc2ad..305975e 100644
--- a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs
@@ -38,7 +38,23 @@ namespace OpenSim.Region.Framework.Interfaces
38 public interface IInventoryAccessModule 38 public interface IInventoryAccessModule
39 { 39 {
40 UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data); 40 UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data);
41 UUID DeleteToInventory(DeRezAction action, UUID folderID, List<SceneObjectGroup> objectGroups, IClientAPI remoteClient); 41
42 /// <summary>
43 /// Copy objects to a user's inventory.
44 /// </summary>
45 /// <remarks>
46 /// Is it left to the caller to delete them from the scene if required.
47 /// </remarks>
48 /// <param name="action"></param>
49 /// <param name="folderID"></param>
50 /// <param name="objectGroups"></param>
51 /// <param name="remoteClient"></param>
52 /// <returns>
53 /// Returns the UUID of the newly created item asset (not the item itself).
54 /// FIXME: This is not very useful. It would be far more useful to return a list of items instead.
55 /// </returns>
56 UUID CopyToInventory(DeRezAction action, UUID folderID, List<SceneObjectGroup> objectGroups, IClientAPI remoteClient);
57
42 SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, 58 SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
43 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 59 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
44 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment); 60 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment);
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index 8feb022..3423542 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -143,7 +143,8 @@ namespace OpenSim.Region.Framework.Scenes
143 { 143 {
144 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 144 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
145 if (invAccess != null) 145 if (invAccess != null)
146 invAccess.DeleteToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient); 146 invAccess.CopyToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient);
147
147 if (x.permissionToDelete) 148 if (x.permissionToDelete)
148 { 149 {
149 foreach (SceneObjectGroup g in x.objectGroups) 150 foreach (SceneObjectGroup g in x.objectGroups)
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index 107e859..e72e851 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -155,10 +155,6 @@
155 ; it may cause unexpected physics problems. 155 ; it may cause unexpected physics problems.
156 ;UseMeshiesPhysicsMesh = false 156 ;UseMeshiesPhysicsMesh = false
157 157
158 ; enable / disable Collada mesh support
159 ; default is true
160 ; ColladaMesh = true
161
162 ; Choose one of the physics engines below 158 ; Choose one of the physics engines below
163 ; OpenDynamicsEngine is by some distance the most developed physics engine 159 ; OpenDynamicsEngine is by some distance the most developed physics engine
164 ; basicphysics effectively does not model physics at all, making all objects phantom 160 ; basicphysics effectively does not model physics at all, making all objects phantom
@@ -453,6 +449,19 @@
453 ; ForwardOfflineGroupMessages = true 449 ; ForwardOfflineGroupMessages = true
454 450
455 451
452[Inventory]
453 ; Control whether multiple objects sent to inventory should be coaleseced into a single item
454 ; There are still some issues with coalescence, including the fact that rotation is not restored
455 ; and some assets may be missing from archive files.
456 CoalesceMultipleObjectsToInventory = true
457
458
459[Mesh]
460 ; enable / disable Collada mesh support
461 ; default is true
462 ; ColladaMesh = true
463
464
456[ODEPhysicsSettings] 465[ODEPhysicsSettings]
457 ;## 466 ;##
458 ;## World Settings 467 ;## World Settings