diff options
Diffstat (limited to 'OpenSim/Region')
5 files changed, 258 insertions, 104 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs index ff4ec4c..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,44 +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 | // m_log.DebugFormat("[XFER]: Asked to update item {0} ({1})", | ||
172 | // item.Name, item.ID); | ||
173 | |||
174 | // Here we need to get the old asset to extract the | ||
175 | // texture UUIDs if it's a wearable. | ||
176 | if (item.AssetType == (int)AssetType.Bodypart || | ||
177 | item.AssetType == (int)AssetType.Clothing) | ||
178 | { | ||
179 | AssetBase oldAsset = m_Scene.AssetService.Get(item.AssetID.ToString()); | ||
180 | if (oldAsset != null) | ||
181 | XferUploaders[transactionID].SetOldData(oldAsset.Data); | ||
182 | } | ||
183 | |||
184 | AssetBase asset = GetTransactionAsset(transactionID); | ||
185 | 248 | ||
186 | if (asset != null) | 249 | lock (XferUploaders) |
187 | { | 250 | { |
188 | asset.FullID = UUID.Random(); | 251 | if (XferUploaders.ContainsKey(transactionID)) |
189 | asset.Name = item.Name; | 252 | uploader = XferUploaders[transactionID]; |
190 | asset.Description = item.Description; | 253 | } |
191 | asset.Type = (sbyte)item.AssetType; | ||
192 | item.AssetID = asset.FullID; | ||
193 | |||
194 | m_Scene.AssetService.Store(asset); | ||
195 | |||
196 | IInventoryService invService = m_Scene.InventoryService; | ||
197 | invService.UpdateItem(item); | ||
198 | 254 | ||
199 | // m_log.DebugFormat("[XFER]: Updated item {0} ({1}) with asset {2}", | 255 | if (uploader != null) |
200 | // item.Name, item.ID, asset.FullID); | 256 | { |
201 | } | 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); | ||
202 | } | 264 | } |
203 | } | 265 | } |
204 | } | 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 a5dcdcc..4cedfe6 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs | |||
@@ -48,11 +48,21 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
48 | }; | 48 | }; |
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> | ||
52 | /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we | ||
53 | /// are performing a delayed update. | ||
54 | /// </summary> | ||
55 | AgentAssetTransactions m_transactions; | ||
56 | |||
51 | private AssetBase m_asset; | 57 | private AssetBase m_asset; |
52 | private UUID InventFolder = UUID.Zero; | 58 | private UUID InventFolder = UUID.Zero; |
53 | private sbyte invType = 0; | 59 | private sbyte invType = 0; |
60 | |||
54 | private bool m_createItem = false; | 61 | private bool m_createItem = false; |
55 | private uint m_createItemCallback = 0; | 62 | private uint m_createItemCallback = 0; |
63 | private bool m_updateItem = false; | ||
64 | private InventoryItemBase m_updateItemData; | ||
65 | |||
56 | private string m_description = String.Empty; | 66 | private string m_description = String.Empty; |
57 | private bool m_dumpAssetToFile; | 67 | private bool m_dumpAssetToFile; |
58 | private bool m_finished = false; | 68 | private bool m_finished = false; |
@@ -67,9 +77,11 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
67 | public ulong XferID; | 77 | public ulong XferID; |
68 | private Scene m_Scene; | 78 | private Scene m_Scene; |
69 | 79 | ||
70 | public AssetXferUploader(Scene scene, bool dumpAssetToFile) | 80 | public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile) |
71 | { | 81 | { |
82 | m_transactions = transactions; | ||
72 | m_Scene = scene; | 83 | m_Scene = scene; |
84 | m_asset = new AssetBase() { FullID = assetID }; | ||
73 | m_dumpAssetToFile = dumpAssetToFile; | 85 | m_dumpAssetToFile = dumpAssetToFile; |
74 | } | 86 | } |
75 | 87 | ||
@@ -82,6 +94,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
82 | /// <returns>True if the transfer is complete, false otherwise or if the xferID was not valid</returns> | 94 | /// <returns>True if the transfer is complete, false otherwise or if the xferID was not valid</returns> |
83 | public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data) | 95 | public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data) |
84 | { | 96 | { |
97 | // m_log.DebugFormat( | ||
98 | // "[ASSET XFER UPLOADER]: Received packet {0} for xfer {1} (data length {2})", | ||
99 | // packetID, xferID, data.Length); | ||
100 | |||
85 | if (XferID == xferID) | 101 | if (XferID == xferID) |
86 | { | 102 | { |
87 | if (m_asset.Data.Length > 1) | 103 | if (m_asset.Data.Length > 1) |
@@ -116,16 +132,20 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
116 | /// <param name="xferID"></param> | 132 | /// <param name="xferID"></param> |
117 | /// <param name="packetID"></param> | 133 | /// <param name="packetID"></param> |
118 | /// <param name="data"></param> | 134 | /// <param name="data"></param> |
119 | /// <returns>True if the transfer is complete, false otherwise</returns> | 135 | public void Initialise(IClientAPI remoteClient, UUID assetID, |
120 | public bool Initialise(IClientAPI remoteClient, UUID assetID, | ||
121 | UUID transaction, sbyte type, byte[] data, bool storeLocal, | 136 | UUID transaction, sbyte type, byte[] data, bool storeLocal, |
122 | bool tempFile) | 137 | bool tempFile) |
123 | { | 138 | { |
139 | // 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}", | ||
141 | // remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length); | ||
142 | |||
124 | ourClient = remoteClient; | 143 | ourClient = remoteClient; |
125 | m_asset = new AssetBase(assetID, "blank", type, | 144 | m_asset.Name = "blank"; |
126 | remoteClient.AgentId.ToString()); | ||
127 | m_asset.Data = data; | ||
128 | m_asset.Description = "empty"; | 145 | m_asset.Description = "empty"; |
146 | m_asset.Type = type; | ||
147 | m_asset.CreatorID = remoteClient.AgentId.ToString(); | ||
148 | m_asset.Data = data; | ||
129 | m_asset.Local = storeLocal; | 149 | m_asset.Local = storeLocal; |
130 | m_asset.Temporary = tempFile; | 150 | m_asset.Temporary = tempFile; |
131 | 151 | ||
@@ -135,21 +155,22 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
135 | if (m_asset.Data.Length > 2) | 155 | if (m_asset.Data.Length > 2) |
136 | { | 156 | { |
137 | SendCompleteMessage(); | 157 | SendCompleteMessage(); |
138 | return true; | ||
139 | } | 158 | } |
140 | else | 159 | else |
141 | { | 160 | { |
142 | RequestStartXfer(); | 161 | RequestStartXfer(); |
143 | } | 162 | } |
144 | |||
145 | return false; | ||
146 | } | 163 | } |
147 | 164 | ||
148 | protected void RequestStartXfer() | 165 | protected void RequestStartXfer() |
149 | { | 166 | { |
150 | XferID = Util.GetNextXferID(); | 167 | XferID = Util.GetNextXferID(); |
151 | ourClient.SendXferRequest(XferID, m_asset.Type, m_asset.FullID, | 168 | |
152 | 0, new byte[0]); | 169 | // m_log.DebugFormat( |
170 | // "[ASSET XFER UPLOADER]: Requesting Xfer of asset {0}, type {1}, transfer id {2} from {3}", | ||
171 | // m_asset.FullID, m_asset.Type, XferID, ourClient.Name); | ||
172 | |||
173 | ourClient.SendXferRequest(XferID, m_asset.Type, m_asset.FullID, 0, new byte[0]); | ||
153 | } | 174 | } |
154 | 175 | ||
155 | protected void SendCompleteMessage() | 176 | protected void SendCompleteMessage() |
@@ -157,18 +178,32 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
157 | ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, | 178 | ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, |
158 | m_asset.FullID); | 179 | m_asset.FullID); |
159 | 180 | ||
160 | m_finished = true; | 181 | // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create |
161 | if (m_createItem) | 182 | // message from other client UDP. |
183 | lock (this) | ||
162 | { | 184 | { |
163 | DoCreateItem(m_createItemCallback); | 185 | m_finished = true; |
164 | } | 186 | if (m_createItem) |
165 | else if (m_storeLocal) | 187 | { |
166 | { | 188 | DoCreateItem(m_createItemCallback); |
167 | m_Scene.AssetService.Store(m_asset); | 189 | } |
190 | else if (m_updateItem) | ||
191 | { | ||
192 | StoreAssetForItemUpdate(m_updateItemData); | ||
193 | |||
194 | // Remove ourselves from the list of transactions if completion was delayed until the transaction | ||
195 | // was complete. | ||
196 | // TODO: Should probably do the same for create item. | ||
197 | m_transactions.RemoveXferUploader(TransactionID); | ||
198 | } | ||
199 | else if (m_storeLocal) | ||
200 | { | ||
201 | m_Scene.AssetService.Store(m_asset); | ||
202 | } | ||
168 | } | 203 | } |
169 | 204 | ||
170 | m_log.DebugFormat( | 205 | m_log.DebugFormat( |
171 | "[ASSET TRANSACTIONS]: Uploaded asset {0} for transaction {1}", | 206 | "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}", |
172 | m_asset.FullID, TransactionID); | 207 | m_asset.FullID, TransactionID); |
173 | 208 | ||
174 | if (m_dumpAssetToFile) | 209 | if (m_dumpAssetToFile) |
@@ -214,18 +249,66 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
214 | m_asset.Description = description; | 249 | m_asset.Description = description; |
215 | m_asset.Type = type; | 250 | m_asset.Type = type; |
216 | 251 | ||
252 | // We must lock to avoid a race with a separate thread uploading the asset. | ||
253 | lock (this) | ||
254 | { | ||
255 | if (m_finished) | ||
256 | { | ||
257 | DoCreateItem(callbackID); | ||
258 | } | ||
259 | else | ||
260 | { | ||
261 | m_createItem = true; //set flag so the inventory item is created when upload is complete | ||
262 | m_createItemCallback = callbackID; | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | } | ||
267 | |||
268 | public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) | ||
269 | { | ||
270 | // We must lock to avoid a race with a separate thread uploading the asset. | ||
271 | lock (this) | ||
272 | { | ||
273 | m_asset.Name = item.Name; | ||
274 | m_asset.Description = item.Description; | ||
275 | m_asset.Type = (sbyte)item.AssetType; | ||
276 | |||
277 | // We must always store the item at this point even if the asset hasn't finished uploading, in order | ||
278 | // to avoid a race condition when the appearance module retrieves the item to set the asset id in | ||
279 | // the AvatarAppearance structure. | ||
280 | item.AssetID = m_asset.FullID; | ||
281 | m_Scene.InventoryService.UpdateItem(item); | ||
282 | |||
217 | if (m_finished) | 283 | if (m_finished) |
218 | { | 284 | { |
219 | DoCreateItem(callbackID); | 285 | StoreAssetForItemUpdate(item); |
220 | } | 286 | } |
221 | else | 287 | else |
222 | { | 288 | { |
223 | m_createItem = true; //set flag so the inventory item is created when upload is complete | 289 | // m_log.DebugFormat( |
224 | m_createItemCallback = callbackID; | 290 | // "[ASSET XFER UPLOADER]: Holding update inventory item request {0} for {1} pending completion of asset xfer for transaction {2}", |
291 | // item.Name, remoteClient.Name, transactionID); | ||
292 | |||
293 | m_updateItem = true; | ||
294 | m_updateItemData = item; | ||
225 | } | 295 | } |
226 | } | 296 | } |
227 | } | 297 | } |
228 | 298 | ||
299 | /// <summary> | ||
300 | /// Store the asset for the given item. | ||
301 | /// </summary> | ||
302 | /// <param name="item"></param> | ||
303 | private void StoreAssetForItemUpdate(InventoryItemBase item) | ||
304 | { | ||
305 | // m_log.DebugFormat( | ||
306 | // "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", | ||
307 | // m_asset.FullID, item.Name, ourClient.Name); | ||
308 | |||
309 | m_Scene.AssetService.Store(m_asset); | ||
310 | } | ||
311 | |||
229 | private void DoCreateItem(uint callbackID) | 312 | private void DoCreateItem(uint callbackID) |
230 | { | 313 | { |
231 | ValidateAssets(); | 314 | ValidateAssets(); |
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 | ||
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 931fedc..53f0f2e 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | |||
@@ -316,6 +316,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
316 | public void UpdateInventoryItemAsset(IClientAPI remoteClient, UUID transactionID, | 316 | public void UpdateInventoryItemAsset(IClientAPI remoteClient, UUID transactionID, |
317 | UUID itemID, InventoryItemBase itemUpd) | 317 | UUID itemID, InventoryItemBase itemUpd) |
318 | { | 318 | { |
319 | // m_log.DebugFormat( | ||
320 | // "[USER INVENTORY]: Updating asset for item {0} {1}, transaction ID {2} for {3}", | ||
321 | // itemID, itemUpd.Name, transactionID, remoteClient.Name); | ||
322 | |||
319 | // This one will let people set next perms on items in agent | 323 | // This one will let people set next perms on items in agent |
320 | // inventory. Rut-Roh. Whatever. Make this secure. Yeah. | 324 | // inventory. Rut-Roh. Whatever. Make this secure. Yeah. |
321 | // | 325 | // |
@@ -368,8 +372,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
368 | IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>(); | 372 | IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>(); |
369 | if (agentTransactions != null) | 373 | if (agentTransactions != null) |
370 | { | 374 | { |
371 | agentTransactions.HandleItemUpdateFromTransaction( | 375 | agentTransactions.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); |
372 | remoteClient, transactionID, item); | ||
373 | } | 376 | } |
374 | } | 377 | } |
375 | } | 378 | } |