aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2012-09-25 21:35:39 +0100
committerJustin Clark-Casey (justincc)2012-09-25 21:35:39 +0100
commit4fc0cfba3ce1e6545e334f8e34a0e5b45274081e (patch)
tree9ab2bc50763d2858ccd5632294d6697574bd1d4c /OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
parentDocumenting object-related events (diff)
downloadopensim-SC_OLD-4fc0cfba3ce1e6545e334f8e34a0e5b45274081e.zip
opensim-SC_OLD-4fc0cfba3ce1e6545e334f8e34a0e5b45274081e.tar.gz
opensim-SC_OLD-4fc0cfba3ce1e6545e334f8e34a0e5b45274081e.tar.bz2
opensim-SC_OLD-4fc0cfba3ce1e6545e334f8e34a0e5b45274081e.tar.xz
Fix occasional race condition failure when creating new clothing/body parts in the viewer or updating existing assets.
On creating these items, the viewer sends a UDP AssetUploadRequest followed by a CreateInventoryItem. It was possible for the CreateInventoryItem/UpdateInventoryItem to occasionally outrace the AssetUploadRequest and fail to find an initialized Xfer object, at which point the item create would fail. So instead we always set up a Xfer object on either the asset or inventory item update request. This does not introduce a new race because code already exists to delay the item operation until the asset is uploaded if necessary (but this only worked if the xfer object already existed)
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs72
1 files changed, 54 insertions, 18 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
index ec4dfd0..9f05120 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
@@ -41,11 +41,26 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
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> 43 /// <summary>
44 /// Upload state.
45 /// </summary>
46 /// <remarks>
47 /// New -> Uploading -> Complete
48 /// </remarks>
49 private enum UploadState
50 {
51 New,
52 Uploading,
53 Complete
54 }
55
56 /// <summary>
44 /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we 57 /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we
45 /// are performing a delayed update. 58 /// are performing a delayed update.
46 /// </summary> 59 /// </summary>
47 AgentAssetTransactions m_transactions; 60 AgentAssetTransactions m_transactions;
48 61
62 private UploadState m_uploadState = UploadState.New;
63
49 private AssetBase m_asset; 64 private AssetBase m_asset;
50 private UUID InventFolder = UUID.Zero; 65 private UUID InventFolder = UUID.Zero;
51 private sbyte invType = 0; 66 private sbyte invType = 0;
@@ -57,7 +72,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
57 72
58 private string m_description = String.Empty; 73 private string m_description = String.Empty;
59 private bool m_dumpAssetToFile; 74 private bool m_dumpAssetToFile;
60 private bool m_finished = false;
61 private string m_name = String.Empty; 75 private string m_name = String.Empty;
62 private bool m_storeLocal; 76 private bool m_storeLocal;
63 private uint nextPerm = 0; 77 private uint nextPerm = 0;
@@ -68,11 +82,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
68 public ulong XferID; 82 public ulong XferID;
69 private Scene m_Scene; 83 private Scene m_Scene;
70 84
71 public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile) 85 public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, bool dumpAssetToFile)
72 { 86 {
73 m_transactions = transactions; 87 m_transactions = transactions;
74 m_Scene = scene; 88 m_Scene = scene;
75 m_asset = new AssetBase() { FullID = assetID };
76 m_dumpAssetToFile = dumpAssetToFile; 89 m_dumpAssetToFile = dumpAssetToFile;
77 } 90 }
78 91
@@ -118,20 +131,43 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
118 } 131 }
119 132
120 /// <summary> 133 /// <summary>
121 /// Initialise asset transfer from the client 134 /// Start asset transfer from the client
122 /// </summary> 135 /// </summary>
123 /// <param name="xferID"></param> 136 /// <param name="remoteClient"></param>
124 /// <param name="packetID"></param> 137 /// <param name="assetID"></param>
125 /// <param name="data"></param> 138 /// <param name="transaction"></param>
126 public void Initialise(IClientAPI remoteClient, UUID assetID, 139 /// <param name="type"></param>
127 UUID transaction, sbyte type, byte[] data, bool storeLocal, 140 /// <param name="data">
128 bool tempFile) 141 /// Optional data. If present then the asset is created immediately with this data
142 /// rather than requesting an upload from the client. The data must be longer than 2 bytes.
143 /// </param>
144 /// <param name="storeLocal"></param>
145 /// <param name="tempFile"></param>
146 public void StartUpload(
147 IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, byte[] data, bool storeLocal,
148 bool tempFile)
129 { 149 {
130// m_log.DebugFormat( 150// 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}", 151// "[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); 152// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length);
133 153
154 lock (this)
155 {
156 if (m_uploadState != UploadState.New)
157 {
158 m_log.WarnFormat(
159 "[ASSET XFER UPLOADER]: Tried to start upload of asset {0}, transaction {1} for {2} but this is already in state {3}. Aborting.",
160 assetID, transaction, remoteClient.Name, m_uploadState);
161
162 return;
163 }
164
165 m_uploadState = UploadState.Uploading;
166 }
167
134 ourClient = remoteClient; 168 ourClient = remoteClient;
169
170 m_asset = new AssetBase() { FullID = assetID };
135 m_asset.Name = "blank"; 171 m_asset.Name = "blank";
136 m_asset.Description = "empty"; 172 m_asset.Description = "empty";
137 m_asset.Type = type; 173 m_asset.Type = type;
@@ -166,14 +202,14 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
166 202
167 protected void SendCompleteMessage() 203 protected void SendCompleteMessage()
168 { 204 {
169 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true,
170 m_asset.FullID);
171
172 // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create 205 // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create
173 // message from other client UDP. 206 // message from other client UDP.
174 lock (this) 207 lock (this)
175 { 208 {
176 m_finished = true; 209 m_uploadState = UploadState.Complete;
210
211 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID);
212
177 if (m_createItem) 213 if (m_createItem)
178 { 214 {
179 DoCreateItem(m_createItemCallback); 215 DoCreateItem(m_createItemCallback);
@@ -243,7 +279,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
243 // We must lock to avoid a race with a separate thread uploading the asset. 279 // We must lock to avoid a race with a separate thread uploading the asset.
244 lock (this) 280 lock (this)
245 { 281 {
246 if (m_finished) 282 if (m_uploadState == UploadState.Complete)
247 { 283 {
248 DoCreateItem(callbackID); 284 DoCreateItem(callbackID);
249 } 285 }
@@ -271,7 +307,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
271 item.AssetID = m_asset.FullID; 307 item.AssetID = m_asset.FullID;
272 m_Scene.InventoryService.UpdateItem(item); 308 m_Scene.InventoryService.UpdateItem(item);
273 309
274 if (m_finished) 310 if (m_uploadState == UploadState.Complete)
275 { 311 {
276 StoreAssetForItemUpdate(item); 312 StoreAssetForItemUpdate(item);
277 } 313 }
@@ -334,7 +370,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
334 /// <returns>null if the asset has not finished uploading</returns> 370 /// <returns>null if the asset has not finished uploading</returns>
335 public AssetBase GetAssetData() 371 public AssetBase GetAssetData()
336 { 372 {
337 if (m_finished) 373 if (m_uploadState == UploadState.Complete)
338 { 374 {
339 return m_asset; 375 return m_asset;
340 } 376 }
@@ -342,4 +378,4 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
342 return null; 378 return null;
343 } 379 }
344 } 380 }
345} 381} \ No newline at end of file