aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
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/Agent/AssetTransaction/AssetXferUploader.cs
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 '')
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs127
1 files changed, 105 insertions, 22 deletions
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);