aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2011-09-23 02:59:33 +0100
committerJustin Clark-Casey (justincc)2011-09-23 02:59:33 +0100
commitc8304b7f84b1a8d9fb978cae510f684e36419deb (patch)
tree9b450813d8023df7daf54fd2ee2b8cd19f58eb94 /OpenSim/Region/CoreModules
parentMerge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff)
downloadopensim-SC_OLD-c8304b7f84b1a8d9fb978cae510f684e36419deb.zip
opensim-SC_OLD-c8304b7f84b1a8d9fb978cae510f684e36419deb.tar.gz
opensim-SC_OLD-c8304b7f84b1a8d9fb978cae510f684e36419deb.tar.bz2
opensim-SC_OLD-c8304b7f84b1a8d9fb978cae510f684e36419deb.tar.xz
Fix avatar parameter updating for viewer 3 and maybe 2.
When a slider parameter is changed, the viewer uploads a new shape (or other asset) and the item is updated to point to it. Viewer 1 uploaded the data in the initial request itself, so the asset references was almost always correctly updated. However, viewer 3/2 always uploads data in a subsequent xfer, which exposed a race condition where the viewer would make the item update before the asset had uploaded. This commit shuffles the order of operations to avoid this race, the item is updated with the new asset id instead of the old one while the upload was still taking place. A second race had to be fixed where avatar appearance would also be updated with the old asset id rather than the new one. This was fixed by updating the avatar appearance ids when the appearance was actually saved, rather than when the wearables update was made.
Diffstat (limited to 'OpenSim/Region/CoreModules')
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs168
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs25
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs127
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs19
4 files changed, 253 insertions, 86 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index 9d8082b..eed7cd5 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -41,14 +41,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
41 /// </summary> 41 /// </summary>
42 public class AgentAssetTransactions 42 public class AgentAssetTransactions
43 { 43 {
44// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 45
46 // Fields 46 // Fields
47 private bool m_dumpAssetsToFile; 47 private bool m_dumpAssetsToFile;
48 private Scene m_Scene; 48 private Scene m_Scene;
49 public UUID UserID; 49 private UUID UserID;
50 public Dictionary<UUID, AssetXferUploader> XferUploaders = 50 private Dictionary<UUID, AssetXferUploader> XferUploaders = new Dictionary<UUID, AssetXferUploader>();
51 new Dictionary<UUID, AssetXferUploader>();
52 51
53 // Methods 52 // Methods
54 public AgentAssetTransactions(UUID agentID, Scene scene, 53 public AgentAssetTransactions(UUID agentID, Scene scene,
@@ -59,36 +58,94 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
59 m_dumpAssetsToFile = dumpAssetsToFile; 58 m_dumpAssetsToFile = dumpAssetsToFile;
60 } 59 }
61 60
62 public AssetXferUploader RequestXferUploader(UUID transactionID) 61 /// <summary>
62 /// Return a xfer uploader if one does not already exist.
63 /// </summary>
64 /// <param name="transactionID"></param>
65 /// <param name="assetID">
66 /// We must transfer the new asset ID into the uploader on creation, otherwise
67 /// we can see race conditions with other threads which can retrieve an item before it is updated with the new
68 /// asset id.
69 /// </param>
70 /// <returns>
71 /// The xfer uploader requested. Null if one is already in existence.
72 /// FIXME: This is a bizarre thing to do, and is probably meant to signal an error condition if multiple
73 /// transfers are made. Needs to be corrected.
74 /// </returns>
75 public AssetXferUploader RequestXferUploader(UUID transactionID, UUID assetID)
63 { 76 {
64 if (!XferUploaders.ContainsKey(transactionID)) 77 lock (XferUploaders)
65 { 78 {
66 AssetXferUploader uploader = new AssetXferUploader(m_Scene, 79 if (!XferUploaders.ContainsKey(transactionID))
67 m_dumpAssetsToFile);
68
69 lock (XferUploaders)
70 { 80 {
81 AssetXferUploader uploader = new AssetXferUploader(this, m_Scene, assetID, m_dumpAssetsToFile);
82
83// m_log.DebugFormat(
84// "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID);
85
71 XferUploaders.Add(transactionID, uploader); 86 XferUploaders.Add(transactionID, uploader);
72 }
73 87
74 return uploader; 88 return uploader;
89 }
75 } 90 }
91
92 m_log.WarnFormat("[AGENT ASSETS TRANSACTIONS]: Ignoring request for asset xfer uploader {0} since it already exists", transactionID);
93
76 return null; 94 return null;
77 } 95 }
78 96
79 public void HandleXfer(ulong xferID, uint packetID, byte[] data) 97 public void HandleXfer(ulong xferID, uint packetID, byte[] data)
80 { 98 {
99 AssetXferUploader foundUploader = null;
100
81 lock (XferUploaders) 101 lock (XferUploaders)
82 { 102 {
83 foreach (AssetXferUploader uploader in XferUploaders.Values) 103 foreach (AssetXferUploader uploader in XferUploaders.Values)
84 { 104 {
105// m_log.DebugFormat(
106// "[AGENT ASSETS TRANSACTIONS]: In HandleXfer, inspect xfer upload with xfer id {0}",
107// uploader.XferID);
108
85 if (uploader.XferID == xferID) 109 if (uploader.XferID == xferID)
86 { 110 {
87 uploader.HandleXferPacket(xferID, packetID, data); 111 foundUploader = uploader;
88 break; 112 break;
89 } 113 }
90 } 114 }
91 } 115 }
116
117 if (foundUploader != null)
118 {
119// m_log.DebugFormat(
120// "[AGENT ASSETS TRANSACTIONS]: Found xfer uploader for xfer id {0}, packet id {1}, data length {2}",
121// xferID, packetID, data.Length);
122
123 foundUploader.HandleXferPacket(xferID, packetID, data);
124 }
125 else
126 {
127 m_log.ErrorFormat(
128 "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}",
129 xferID, packetID, data.Length);
130 }
131 }
132
133 public bool RemoveXferUploader(UUID transactionID)
134 {
135 lock (XferUploaders)
136 {
137 bool removed = XferUploaders.Remove(transactionID);
138
139 if (!removed)
140 m_log.WarnFormat(
141 "[AGENT ASSET TRANSACTIONS]: Received request to remove xfer uploader with transaction ID {0} but none found",
142 transactionID);
143// else
144// m_log.DebugFormat(
145// "[AGENT ASSET TRANSACTIONS]: Removed xfer uploader with transaction ID {0}", transactionID);
146
147 return removed;
148 }
92 } 149 }
93 150
94 public void RequestCreateInventoryItem(IClientAPI remoteClient, 151 public void RequestCreateInventoryItem(IClientAPI remoteClient,
@@ -96,16 +153,24 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
96 string description, string name, sbyte invType, 153 string description, string name, sbyte invType,
97 sbyte type, byte wearableType, uint nextOwnerMask) 154 sbyte type, byte wearableType, uint nextOwnerMask)
98 { 155 {
99 if (XferUploaders.ContainsKey(transactionID)) 156 AssetXferUploader uploader = null;
157
158 lock (XferUploaders)
100 { 159 {
101 XferUploaders[transactionID].RequestCreateInventoryItem( 160 if (XferUploaders.ContainsKey(transactionID))
102 remoteClient, transactionID, folderID, 161 uploader = XferUploaders[transactionID];
103 callbackID, description, name, invType, type,
104 wearableType, nextOwnerMask);
105 } 162 }
106 }
107
108 163
164 if (uploader != null)
165 uploader.RequestCreateInventoryItem(
166 remoteClient, transactionID, folderID,
167 callbackID, description, name, invType, type,
168 wearableType, nextOwnerMask);
169 else
170 m_log.ErrorFormat(
171 "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to create inventory item {1} from {2}",
172 transactionID, name, remoteClient.Name);
173 }
109 174
110 /// <summary> 175 /// <summary>
111 /// Get an uploaded asset. If the data is successfully retrieved, 176 /// Get an uploaded asset. If the data is successfully retrieved,
@@ -113,19 +178,18 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
113 /// </summary> 178 /// </summary>
114 /// <param name="transactionID"></param> 179 /// <param name="transactionID"></param>
115 /// <returns>The asset if the upload has completed, null if it has not.</returns> 180 /// <returns>The asset if the upload has completed, null if it has not.</returns>
116 public AssetBase GetTransactionAsset(UUID transactionID) 181 private AssetBase GetTransactionAsset(UUID transactionID)
117 { 182 {
118 if (XferUploaders.ContainsKey(transactionID)) 183 lock (XferUploaders)
119 { 184 {
120 AssetXferUploader uploader = XferUploaders[transactionID]; 185 if (XferUploaders.ContainsKey(transactionID))
121 AssetBase asset = uploader.GetAssetData();
122
123 lock (XferUploaders)
124 { 186 {
125 XferUploaders.Remove(transactionID); 187 AssetXferUploader uploader = XferUploaders[transactionID];
126 } 188 AssetBase asset = uploader.GetAssetData();
189 RemoveXferUploader(transactionID);
127 190
128 return asset; 191 return asset;
192 }
129 } 193 }
130 194
131 return null; 195 return null;
@@ -135,7 +199,15 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
135 SceneObjectPart part, UUID transactionID, 199 SceneObjectPart part, UUID transactionID,
136 TaskInventoryItem item) 200 TaskInventoryItem item)
137 { 201 {
138 if (XferUploaders.ContainsKey(transactionID)) 202 AssetXferUploader uploader = null;
203
204 lock (XferUploaders)
205 {
206 if (XferUploaders.ContainsKey(transactionID))
207 uploader = XferUploaders[transactionID];
208 }
209
210 if (uploader != null)
139 { 211 {
140 AssetBase asset = GetTransactionAsset(transactionID); 212 AssetBase asset = GetTransactionAsset(transactionID);
141 213
@@ -161,28 +233,34 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
161 m_Scene.AssetService.Store(asset); 233 m_Scene.AssetService.Store(asset);
162 } 234 }
163 } 235 }
236 else
237 {
238 m_log.ErrorFormat(
239 "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update task inventory item {1} in {2}",
240 transactionID, item.Name, part.Name);
241 }
164 } 242 }
165 243
166 public void RequestUpdateInventoryItem(IClientAPI remoteClient, 244 public void RequestUpdateInventoryItem(IClientAPI remoteClient,
167 UUID transactionID, InventoryItemBase item) 245 UUID transactionID, InventoryItemBase item)
168 { 246 {
169 if (XferUploaders.ContainsKey(transactionID)) 247 AssetXferUploader uploader = null;
170 {
171 AssetBase asset = GetTransactionAsset(transactionID);
172 248
173 if (asset != null) 249 lock (XferUploaders)
174 { 250 {
175 asset.FullID = UUID.Random(); 251 if (XferUploaders.ContainsKey(transactionID))
176 asset.Name = item.Name; 252 uploader = XferUploaders[transactionID];
177 asset.Description = item.Description; 253 }
178 asset.Type = (sbyte)item.AssetType;
179 item.AssetID = asset.FullID;
180
181 m_Scene.AssetService.Store(asset);
182 254
183 IInventoryService invService = m_Scene.InventoryService; 255 if (uploader != null)
184 invService.UpdateItem(item); 256 {
185 } 257 uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item);
258 }
259 else
260 {
261 m_log.ErrorFormat(
262 "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update inventory item {1} for {2}",
263 transactionID, item.Name, remoteClient.Name);
186 } 264 }
187 } 265 }
188 } 266 }
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
index 82558de..a28d5d7 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
@@ -172,11 +172,12 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
172 /// <summary> 172 /// <summary>
173 /// Update an inventory item with data that has been received through a 173 /// Update an inventory item with data that has been received through a
174 /// transaction. 174 /// transaction.
175 /// 175 /// </summary>
176 /// <remarks>
176 /// This is called when clothing or body parts are updated (for 177 /// This is called when clothing or body parts are updated (for
177 /// instance, with new textures or colours). It may also be called in 178 /// instance, with new textures or colours). It may also be called in
178 /// other situations. 179 /// other situations.
179 /// </summary> 180 /// </remarks>
180 /// <param name="remoteClient"></param> 181 /// <param name="remoteClient"></param>
181 /// <param name="transactionID"></param> 182 /// <param name="transactionID"></param>
182 /// <param name="item"></param> 183 /// <param name="item"></param>
@@ -184,14 +185,12 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
184 UUID transactionID, InventoryItemBase item) 185 UUID transactionID, InventoryItemBase item)
185 { 186 {
186// m_log.DebugFormat( 187// m_log.DebugFormat(
187// "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}", 188// "[ASSET TRANSACTION MODULE]: Called HandleItemUpdateFromTransaction with item {0}",
188// item.Name); 189// item.Name);
189 190
190 AgentAssetTransactions transactions = 191 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
191 GetUserTransactions(remoteClient.AgentId);
192 192
193 transactions.RequestUpdateInventoryItem(remoteClient, 193 transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item);
194 transactionID, item);
195 } 194 }
196 195
197 /// <summary> 196 /// <summary>
@@ -255,11 +254,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
255 } 254 }
256 } 255 }
257 256
258 AgentAssetTransactions transactions = 257 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
259 GetUserTransactions(remoteClient.AgentId); 258 AssetXferUploader uploader = transactions.RequestXferUploader(transaction, assetID);
260
261 AssetXferUploader uploader =
262 transactions.RequestXferUploader(transaction);
263 259
264 if (uploader != null) 260 if (uploader != null)
265 { 261 {
@@ -279,9 +275,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
279 public void HandleXfer(IClientAPI remoteClient, ulong xferID, 275 public void HandleXfer(IClientAPI remoteClient, ulong xferID,
280 uint packetID, byte[] data) 276 uint packetID, byte[] data)
281 { 277 {
282 //m_log.Debug("xferID: " + xferID + " packetID: " + packetID + " data!"); 278// m_log.Debug("xferID: " + xferID + " packetID: " + packetID + " data length " + data.Length);
283 AgentAssetTransactions transactions = 279 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
284 GetUserTransactions(remoteClient.AgentId);
285 280
286 transactions.HandleXfer(xferID, packetID, data); 281 transactions.HandleXfer(xferID, packetID, data);
287 } 282 }
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
index a7929ba..ec4dfd0 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
@@ -40,11 +40,21 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
40 { 40 {
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42 42
43 /// <summary>
44 /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we
45 /// are performing a delayed update.
46 /// </summary>
47 AgentAssetTransactions m_transactions;
48
43 private AssetBase m_asset; 49 private AssetBase m_asset;
44 private UUID InventFolder = UUID.Zero; 50 private UUID InventFolder = UUID.Zero;
45 private sbyte invType = 0; 51 private sbyte invType = 0;
52
46 private bool m_createItem = false; 53 private bool m_createItem = false;
47 private uint m_createItemCallback = 0; 54 private uint m_createItemCallback = 0;
55 private bool m_updateItem = false;
56 private InventoryItemBase m_updateItemData;
57
48 private string m_description = String.Empty; 58 private string m_description = String.Empty;
49 private bool m_dumpAssetToFile; 59 private bool m_dumpAssetToFile;
50 private bool m_finished = false; 60 private bool m_finished = false;
@@ -58,9 +68,11 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
58 public ulong XferID; 68 public ulong XferID;
59 private Scene m_Scene; 69 private Scene m_Scene;
60 70
61 public AssetXferUploader(Scene scene, bool dumpAssetToFile) 71 public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile)
62 { 72 {
73 m_transactions = transactions;
63 m_Scene = scene; 74 m_Scene = scene;
75 m_asset = new AssetBase() { FullID = assetID };
64 m_dumpAssetToFile = dumpAssetToFile; 76 m_dumpAssetToFile = dumpAssetToFile;
65 } 77 }
66 78
@@ -73,6 +85,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
73 /// <returns>True if the transfer is complete, false otherwise or if the xferID was not valid</returns> 85 /// <returns>True if the transfer is complete, false otherwise or if the xferID was not valid</returns>
74 public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data) 86 public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data)
75 { 87 {
88// m_log.DebugFormat(
89// "[ASSET XFER UPLOADER]: Received packet {0} for xfer {1} (data length {2})",
90// packetID, xferID, data.Length);
91
76 if (XferID == xferID) 92 if (XferID == xferID)
77 { 93 {
78 if (m_asset.Data.Length > 1) 94 if (m_asset.Data.Length > 1)
@@ -107,16 +123,20 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
107 /// <param name="xferID"></param> 123 /// <param name="xferID"></param>
108 /// <param name="packetID"></param> 124 /// <param name="packetID"></param>
109 /// <param name="data"></param> 125 /// <param name="data"></param>
110 /// <returns>True if the transfer is complete, false otherwise</returns> 126 public void Initialise(IClientAPI remoteClient, UUID assetID,
111 public bool Initialise(IClientAPI remoteClient, UUID assetID,
112 UUID transaction, sbyte type, byte[] data, bool storeLocal, 127 UUID transaction, sbyte type, byte[] data, bool storeLocal,
113 bool tempFile) 128 bool tempFile)
114 { 129 {
130// m_log.DebugFormat(
131// "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}",
132// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length);
133
115 ourClient = remoteClient; 134 ourClient = remoteClient;
116 m_asset = new AssetBase(assetID, "blank", type, 135 m_asset.Name = "blank";
117 remoteClient.AgentId.ToString());
118 m_asset.Data = data;
119 m_asset.Description = "empty"; 136 m_asset.Description = "empty";
137 m_asset.Type = type;
138 m_asset.CreatorID = remoteClient.AgentId.ToString();
139 m_asset.Data = data;
120 m_asset.Local = storeLocal; 140 m_asset.Local = storeLocal;
121 m_asset.Temporary = tempFile; 141 m_asset.Temporary = tempFile;
122 142
@@ -126,21 +146,22 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
126 if (m_asset.Data.Length > 2) 146 if (m_asset.Data.Length > 2)
127 { 147 {
128 SendCompleteMessage(); 148 SendCompleteMessage();
129 return true;
130 } 149 }
131 else 150 else
132 { 151 {
133 RequestStartXfer(); 152 RequestStartXfer();
134 } 153 }
135
136 return false;
137 } 154 }
138 155
139 protected void RequestStartXfer() 156 protected void RequestStartXfer()
140 { 157 {
141 XferID = Util.GetNextXferID(); 158 XferID = Util.GetNextXferID();
142 ourClient.SendXferRequest(XferID, m_asset.Type, m_asset.FullID, 159
143 0, new byte[0]); 160// m_log.DebugFormat(
161// "[ASSET XFER UPLOADER]: Requesting Xfer of asset {0}, type {1}, transfer id {2} from {3}",
162// m_asset.FullID, m_asset.Type, XferID, ourClient.Name);
163
164 ourClient.SendXferRequest(XferID, m_asset.Type, m_asset.FullID, 0, new byte[0]);
144 } 165 }
145 166
146 protected void SendCompleteMessage() 167 protected void SendCompleteMessage()
@@ -148,18 +169,32 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
148 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, 169 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true,
149 m_asset.FullID); 170 m_asset.FullID);
150 171
151 m_finished = true; 172 // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create
152 if (m_createItem) 173 // message from other client UDP.
153 { 174 lock (this)
154 DoCreateItem(m_createItemCallback);
155 }
156 else if (m_storeLocal)
157 { 175 {
158 m_Scene.AssetService.Store(m_asset); 176 m_finished = true;
177 if (m_createItem)
178 {
179 DoCreateItem(m_createItemCallback);
180 }
181 else if (m_updateItem)
182 {
183 StoreAssetForItemUpdate(m_updateItemData);
184
185 // Remove ourselves from the list of transactions if completion was delayed until the transaction
186 // was complete.
187 // TODO: Should probably do the same for create item.
188 m_transactions.RemoveXferUploader(TransactionID);
189 }
190 else if (m_storeLocal)
191 {
192 m_Scene.AssetService.Store(m_asset);
193 }
159 } 194 }
160 195
161 m_log.DebugFormat( 196 m_log.DebugFormat(
162 "[ASSET TRANSACTIONS]: Uploaded asset {0} for transaction {1}", 197 "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}",
163 m_asset.FullID, TransactionID); 198 m_asset.FullID, TransactionID);
164 199
165 if (m_dumpAssetToFile) 200 if (m_dumpAssetToFile)
@@ -205,18 +240,66 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
205 m_asset.Description = description; 240 m_asset.Description = description;
206 m_asset.Type = type; 241 m_asset.Type = type;
207 242
243 // We must lock to avoid a race with a separate thread uploading the asset.
244 lock (this)
245 {
246 if (m_finished)
247 {
248 DoCreateItem(callbackID);
249 }
250 else
251 {
252 m_createItem = true; //set flag so the inventory item is created when upload is complete
253 m_createItemCallback = callbackID;
254 }
255 }
256 }
257 }
258
259 public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item)
260 {
261 // We must lock to avoid a race with a separate thread uploading the asset.
262 lock (this)
263 {
264 m_asset.Name = item.Name;
265 m_asset.Description = item.Description;
266 m_asset.Type = (sbyte)item.AssetType;
267
268 // We must always store the item at this point even if the asset hasn't finished uploading, in order
269 // to avoid a race condition when the appearance module retrieves the item to set the asset id in
270 // the AvatarAppearance structure.
271 item.AssetID = m_asset.FullID;
272 m_Scene.InventoryService.UpdateItem(item);
273
208 if (m_finished) 274 if (m_finished)
209 { 275 {
210 DoCreateItem(callbackID); 276 StoreAssetForItemUpdate(item);
211 } 277 }
212 else 278 else
213 { 279 {
214 m_createItem = true; //set flag so the inventory item is created when upload is complete 280// m_log.DebugFormat(
215 m_createItemCallback = callbackID; 281// "[ASSET XFER UPLOADER]: Holding update inventory item request {0} for {1} pending completion of asset xfer for transaction {2}",
282// item.Name, remoteClient.Name, transactionID);
283
284 m_updateItem = true;
285 m_updateItemData = item;
216 } 286 }
217 } 287 }
218 } 288 }
219 289
290 /// <summary>
291 /// Store the asset for the given item.
292 /// </summary>
293 /// <param name="item"></param>
294 private void StoreAssetForItemUpdate(InventoryItemBase item)
295 {
296// m_log.DebugFormat(
297// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}",
298// m_asset.FullID, item.Name, ourClient.Name);
299
300 m_Scene.AssetService.Store(m_asset);
301 }
302
220 private void DoCreateItem(uint callbackID) 303 private void DoCreateItem(uint callbackID)
221 { 304 {
222 m_Scene.AssetService.Store(m_asset); 305 m_Scene.AssetService.Store(m_asset);
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index bb63bcd..0cadd83 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -211,6 +211,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
211 // Process the visual params, this may change height as well 211 // Process the visual params, this may change height as well
212 if (visualParams != null) 212 if (visualParams != null)
213 { 213 {
214// string[] visualParamsStrings = new string[visualParams.Length];
215// for (int i = 0; i < visualParams.Length; i++)
216// visualParamsStrings[i] = visualParams[i].ToString();
217// m_log.DebugFormat(
218// "[AVFACTORY]: Setting visual params for {0} to {1}",
219// client.Name, string.Join(", ", visualParamsStrings));
220
214 float oldHeight = sp.Appearance.AvatarHeight; 221 float oldHeight = sp.Appearance.AvatarHeight;
215 changed = sp.Appearance.SetVisualParams(visualParams); 222 changed = sp.Appearance.SetVisualParams(visualParams);
216 223
@@ -418,6 +425,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
418 425
419 // m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid); 426 // m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid);
420 427
428 // This could take awhile since it needs to pull inventory
429 // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape
430 // assets and item asset id changes to complete.
431 // I don't think we need to worry about doing this within m_setAppearanceLock since the queueing avoids
432 // multiple save requests.
433 SetAppearanceAssets(sp.UUID, sp.Appearance);
434
421 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); 435 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
422 } 436 }
423 437
@@ -504,9 +518,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
504 518
505 avatAppearance.GetAssetsFrom(sp.Appearance); 519 avatAppearance.GetAssetsFrom(sp.Appearance);
506 520
507 // This could take awhile since it needs to pull inventory
508 SetAppearanceAssets(sp.UUID, ref avatAppearance);
509
510 lock (m_setAppearanceLock) 521 lock (m_setAppearanceLock)
511 { 522 {
512 // Update only those fields that we have changed. This is important because the viewer 523 // Update only those fields that we have changed. This is important because the viewer
@@ -540,7 +551,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
540 return true; 551 return true;
541 } 552 }
542 553
543 private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) 554 private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance)
544 { 555 {
545 IInventoryService invService = m_scene.InventoryService; 556 IInventoryService invService = m_scene.InventoryService;
546 557