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
committerMelanie2012-09-27 15:25:32 +0100
commit1a902fceb54d9501f489b2ce872a0b03b5b17ad5 (patch)
tree53ad2401c2f901a43278068a096f46a04b6485cb /OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
parentMerge commit '77355295dadaf3be54ac29d6b3d30901e95c0a32' into careminster (diff)
downloadopensim-SC-1a902fceb54d9501f489b2ce872a0b03b5b17ad5.zip
opensim-SC-1a902fceb54d9501f489b2ce872a0b03b5b17ad5.tar.gz
opensim-SC-1a902fceb54d9501f489b2ce872a0b03b5b17ad5.tar.bz2
opensim-SC-1a902fceb54d9501f489b2ce872a0b03b5b17ad5.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 'OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs')
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs71
1 files changed, 53 insertions, 18 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
index 4cedfe6..d134c43 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
@@ -49,11 +49,26 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 /// <summary> 51 /// <summary>
52 /// Upload state.
53 /// </summary>
54 /// <remarks>
55 /// New -> Uploading -> Complete
56 /// </remarks>
57 private enum UploadState
58 {
59 New,
60 Uploading,
61 Complete
62 }
63
64 /// <summary>
52 /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we 65 /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we
53 /// are performing a delayed update. 66 /// are performing a delayed update.
54 /// </summary> 67 /// </summary>
55 AgentAssetTransactions m_transactions; 68 AgentAssetTransactions m_transactions;
56 69
70 private UploadState m_uploadState = UploadState.New;
71
57 private AssetBase m_asset; 72 private AssetBase m_asset;
58 private UUID InventFolder = UUID.Zero; 73 private UUID InventFolder = UUID.Zero;
59 private sbyte invType = 0; 74 private sbyte invType = 0;
@@ -65,7 +80,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
65 80
66 private string m_description = String.Empty; 81 private string m_description = String.Empty;
67 private bool m_dumpAssetToFile; 82 private bool m_dumpAssetToFile;
68 private bool m_finished = false;
69 private string m_name = String.Empty; 83 private string m_name = String.Empty;
70 private bool m_storeLocal; 84 private bool m_storeLocal;
71 private uint nextPerm = 0; 85 private uint nextPerm = 0;
@@ -77,11 +91,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
77 public ulong XferID; 91 public ulong XferID;
78 private Scene m_Scene; 92 private Scene m_Scene;
79 93
80 public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile) 94 public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, bool dumpAssetToFile)
81 { 95 {
82 m_transactions = transactions; 96 m_transactions = transactions;
83 m_Scene = scene; 97 m_Scene = scene;
84 m_asset = new AssetBase() { FullID = assetID };
85 m_dumpAssetToFile = dumpAssetToFile; 98 m_dumpAssetToFile = dumpAssetToFile;
86 } 99 }
87 100
@@ -127,20 +140,43 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
127 } 140 }
128 141
129 /// <summary> 142 /// <summary>
130 /// Initialise asset transfer from the client 143 /// Start asset transfer from the client
131 /// </summary> 144 /// </summary>
132 /// <param name="xferID"></param> 145 /// <param name="remoteClient"></param>
133 /// <param name="packetID"></param> 146 /// <param name="assetID"></param>
134 /// <param name="data"></param> 147 /// <param name="transaction"></param>
135 public void Initialise(IClientAPI remoteClient, UUID assetID, 148 /// <param name="type"></param>
136 UUID transaction, sbyte type, byte[] data, bool storeLocal, 149 /// <param name="data">
137 bool tempFile) 150 /// Optional data. If present then the asset is created immediately with this data
151 /// rather than requesting an upload from the client. The data must be longer than 2 bytes.
152 /// </param>
153 /// <param name="storeLocal"></param>
154 /// <param name="tempFile"></param>
155 public void StartUpload(
156 IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, byte[] data, bool storeLocal,
157 bool tempFile)
138 { 158 {
139// m_log.DebugFormat( 159// m_log.DebugFormat(
140// "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}", 160// "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}",
141// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length); 161// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length);
142 162
163 lock (this)
164 {
165 if (m_uploadState != UploadState.New)
166 {
167 m_log.WarnFormat(
168 "[ASSET XFER UPLOADER]: Tried to start upload of asset {0}, transaction {1} for {2} but this is already in state {3}. Aborting.",
169 assetID, transaction, remoteClient.Name, m_uploadState);
170
171 return;
172 }
173
174 m_uploadState = UploadState.Uploading;
175 }
176
143 ourClient = remoteClient; 177 ourClient = remoteClient;
178
179 m_asset = new AssetBase() { FullID = assetID };
144 m_asset.Name = "blank"; 180 m_asset.Name = "blank";
145 m_asset.Description = "empty"; 181 m_asset.Description = "empty";
146 m_asset.Type = type; 182 m_asset.Type = type;
@@ -175,14 +211,14 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
175 211
176 protected void SendCompleteMessage() 212 protected void SendCompleteMessage()
177 { 213 {
178 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true,
179 m_asset.FullID);
180
181 // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create 214 // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create
182 // message from other client UDP. 215 // message from other client UDP.
183 lock (this) 216 lock (this)
184 { 217 {
185 m_finished = true; 218 m_uploadState = UploadState.Complete;
219
220 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID);
221
186 if (m_createItem) 222 if (m_createItem)
187 { 223 {
188 DoCreateItem(m_createItemCallback); 224 DoCreateItem(m_createItemCallback);
@@ -252,7 +288,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
252 // We must lock to avoid a race with a separate thread uploading the asset. 288 // We must lock to avoid a race with a separate thread uploading the asset.
253 lock (this) 289 lock (this)
254 { 290 {
255 if (m_finished) 291 if (m_uploadState == UploadState.Complete)
256 { 292 {
257 DoCreateItem(callbackID); 293 DoCreateItem(callbackID);
258 } 294 }
@@ -280,7 +316,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
280 item.AssetID = m_asset.FullID; 316 item.AssetID = m_asset.FullID;
281 m_Scene.InventoryService.UpdateItem(item); 317 m_Scene.InventoryService.UpdateItem(item);
282 318
283 if (m_finished) 319 if (m_uploadState == UploadState.Complete)
284 { 320 {
285 StoreAssetForItemUpdate(item); 321 StoreAssetForItemUpdate(item);
286 } 322 }
@@ -416,7 +452,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
416 /// <returns>null if the asset has not finished uploading</returns> 452 /// <returns>null if the asset has not finished uploading</returns>
417 public AssetBase GetAssetData() 453 public AssetBase GetAssetData()
418 { 454 {
419 if (m_finished) 455 if (m_uploadState == UploadState.Complete)
420 { 456 {
421 ValidateAssets(); 457 ValidateAssets();
422 return m_asset; 458 return m_asset;
@@ -469,4 +505,3 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
469 } 505 }
470 } 506 }
471} 507}
472