diff options
author | Justin Clark-Casey (justincc) | 2011-09-23 02:59:33 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2011-09-23 02:59:33 +0100 |
commit | c8304b7f84b1a8d9fb978cae510f684e36419deb (patch) | |
tree | 9b450813d8023df7daf54fd2ee2b8cd19f58eb94 /OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs | |
parent | Merge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff) | |
download | opensim-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/Agent/AssetTransaction/AgentAssetsTransactions.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs | 168 |
1 files changed, 123 insertions, 45 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 | } |