diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs | 224 |
1 files changed, 124 insertions, 100 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index 7871eda..f54298c 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs | |||
@@ -35,6 +35,7 @@ using System.Xml; | |||
35 | using log4net; | 35 | using log4net; |
36 | using OpenMetaverse; | 36 | using OpenMetaverse; |
37 | using OpenSim.Framework; | 37 | using OpenSim.Framework; |
38 | using OpenSim.Framework.Serialization.External; | ||
38 | 39 | ||
39 | using OpenSim.Region.Framework.Scenes; | 40 | using OpenSim.Region.Framework.Scenes; |
40 | using OpenSim.Region.Framework.Scenes.Serialization; | 41 | using OpenSim.Region.Framework.Scenes.Serialization; |
@@ -73,6 +74,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
73 | 74 | ||
74 | private AssetMetadata FetchMetadata(string url, UUID assetID) | 75 | private AssetMetadata FetchMetadata(string url, UUID assetID) |
75 | { | 76 | { |
77 | if (string.IsNullOrEmpty(url)) | ||
78 | return null; | ||
79 | |||
76 | if (!url.EndsWith("/") && !url.EndsWith("=")) | 80 | if (!url.EndsWith("/") && !url.EndsWith("=")) |
77 | url = url + "/"; | 81 | url = url + "/"; |
78 | 82 | ||
@@ -92,6 +96,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
92 | AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); | 96 | AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); |
93 | if (asset == null) | 97 | if (asset == null) |
94 | { | 98 | { |
99 | if (string.IsNullOrEmpty(url)) | ||
100 | return null; | ||
101 | |||
95 | if (!url.EndsWith("/") && !url.EndsWith("=")) | 102 | if (!url.EndsWith("/") && !url.EndsWith("=")) |
96 | url = url + "/"; | 103 | url = url + "/"; |
97 | 104 | ||
@@ -109,45 +116,47 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
109 | 116 | ||
110 | public bool PostAsset(string url, AssetBase asset) | 117 | public bool PostAsset(string url, AssetBase asset) |
111 | { | 118 | { |
112 | if (asset != null) | 119 | if (string.IsNullOrEmpty(url)) |
113 | { | 120 | return false; |
114 | if (!url.EndsWith("/") && !url.EndsWith("=")) | ||
115 | url = url + "/"; | ||
116 | 121 | ||
117 | bool success = true; | 122 | if (!url.EndsWith("/") && !url.EndsWith("=")) |
118 | // See long comment in AssetCache.AddAsset | 123 | url = url + "/"; |
119 | if (!asset.Temporary || asset.Local) | ||
120 | { | ||
121 | // We need to copy the asset into a new asset, because | ||
122 | // we need to set its ID to be URL+UUID, so that the | ||
123 | // HGAssetService dispatches it to the remote grid. | ||
124 | // It's not pretty, but the best that can be done while | ||
125 | // not having a global naming infrastructure | ||
126 | AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID); | ||
127 | Copy(asset, asset1); | ||
128 | asset1.ID = url + asset.ID; | ||
129 | |||
130 | AdjustIdentifiers(asset1.Metadata); | ||
131 | if (asset1.Metadata.Type == (sbyte)AssetType.Object) | ||
132 | asset1.Data = AdjustIdentifiers(asset.Data); | ||
133 | else | ||
134 | asset1.Data = asset.Data; | ||
135 | 124 | ||
136 | string id = m_scene.AssetService.Store(asset1); | 125 | if (asset == null) |
137 | if (id == string.Empty) | 126 | { |
138 | { | 127 | m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache."); |
139 | m_log.DebugFormat("[HG ASSET MAPPER]: Asset server {0} did not accept {1}", url, asset.ID); | 128 | return false; |
140 | success = false; | ||
141 | } | ||
142 | else | ||
143 | m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url); | ||
144 | } | ||
145 | return success; | ||
146 | } | 129 | } |
130 | |||
131 | // See long comment in AssetCache.AddAsset | ||
132 | if (asset.Temporary || asset.Local) | ||
133 | return true; | ||
134 | |||
135 | // We need to copy the asset into a new asset, because | ||
136 | // we need to set its ID to be URL+UUID, so that the | ||
137 | // HGAssetService dispatches it to the remote grid. | ||
138 | // It's not pretty, but the best that can be done while | ||
139 | // not having a global naming infrastructure | ||
140 | AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID); | ||
141 | Copy(asset, asset1); | ||
142 | asset1.ID = url + asset.ID; | ||
143 | |||
144 | AdjustIdentifiers(asset1.Metadata); | ||
145 | if (asset1.Metadata.Type == (sbyte)AssetType.Object) | ||
146 | asset1.Data = AdjustIdentifiers(asset.Data); | ||
147 | else | 147 | else |
148 | m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache."); | 148 | asset1.Data = asset.Data; |
149 | 149 | ||
150 | return false; | 150 | string id = m_scene.AssetService.Store(asset1); |
151 | if (String.IsNullOrEmpty(id)) | ||
152 | { | ||
153 | m_log.DebugFormat("[HG ASSET MAPPER]: Asset server {0} did not accept {1}", url, asset.ID); | ||
154 | return false; | ||
155 | } | ||
156 | else { | ||
157 | m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url); | ||
158 | return true; | ||
159 | } | ||
151 | } | 160 | } |
152 | 161 | ||
153 | private void Copy(AssetBase from, AssetBase to) | 162 | private void Copy(AssetBase from, AssetBase to) |
@@ -165,7 +174,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
165 | 174 | ||
166 | private void AdjustIdentifiers(AssetMetadata meta) | 175 | private void AdjustIdentifiers(AssetMetadata meta) |
167 | { | 176 | { |
168 | if (meta.CreatorID != null && meta.CreatorID != string.Empty) | 177 | if (!string.IsNullOrEmpty(meta.CreatorID)) |
169 | { | 178 | { |
170 | UUID uuid = UUID.Zero; | 179 | UUID uuid = UUID.Zero; |
171 | UUID.TryParse(meta.CreatorID, out uuid); | 180 | UUID.TryParse(meta.CreatorID, out uuid); |
@@ -181,49 +190,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
181 | return Utils.StringToBytes(RewriteSOP(xml)); | 190 | return Utils.StringToBytes(RewriteSOP(xml)); |
182 | } | 191 | } |
183 | 192 | ||
184 | protected string RewriteSOP(string xml) | 193 | protected string RewriteSOP(string xmlData) |
185 | { | 194 | { |
186 | XmlDocument doc = new XmlDocument(); | 195 | // Console.WriteLine("Input XML [{0}]", xmlData); |
187 | doc.LoadXml(xml); | 196 | return ExternalRepresentationUtils.RewriteSOP(xmlData, m_scene.Name, m_HomeURI, m_scene.UserAccountService, m_scene.RegionInfo.ScopeID); |
188 | XmlNodeList sops = doc.GetElementsByTagName("SceneObjectPart"); | ||
189 | |||
190 | foreach (XmlNode sop in sops) | ||
191 | { | ||
192 | UserAccount creator = null; | ||
193 | bool hasCreatorData = false; | ||
194 | XmlNodeList nodes = sop.ChildNodes; | ||
195 | foreach (XmlNode node in nodes) | ||
196 | { | ||
197 | if (node.Name == "CreatorID") | ||
198 | { | ||
199 | UUID uuid = UUID.Zero; | ||
200 | UUID.TryParse(node.InnerText, out uuid); | ||
201 | creator = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid); | ||
202 | } | ||
203 | if (node.Name == "CreatorData" && node.InnerText != null && node.InnerText != string.Empty) | ||
204 | hasCreatorData = true; | ||
205 | |||
206 | //if (node.Name == "OwnerID") | ||
207 | //{ | ||
208 | // UserAccount owner = GetUser(node.InnerText); | ||
209 | // if (owner != null) | ||
210 | // node.InnerText = m_ProfileServiceURL + "/" + node.InnerText + "/" + owner.FirstName + " " + owner.LastName; | ||
211 | //} | ||
212 | } | ||
213 | |||
214 | if (!hasCreatorData && creator != null) | ||
215 | { | ||
216 | XmlElement creatorData = doc.CreateElement("CreatorData"); | ||
217 | creatorData.InnerText = m_HomeURI + ";" + creator.FirstName + " " + creator.LastName; | ||
218 | sop.AppendChild(creatorData); | ||
219 | } | ||
220 | } | ||
221 | |||
222 | using (StringWriter wr = new StringWriter()) | ||
223 | { | ||
224 | doc.Save(wr); | ||
225 | return wr.ToString(); | ||
226 | } | ||
227 | 197 | ||
228 | } | 198 | } |
229 | 199 | ||
@@ -251,12 +221,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
251 | 221 | ||
252 | // The act of gathering UUIDs downloads some assets from the remote server | 222 | // The act of gathering UUIDs downloads some assets from the remote server |
253 | // but not all... | 223 | // but not all... |
254 | Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); | ||
255 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); | 224 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); |
256 | uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); | 225 | uuidGatherer.AddForInspection(assetID); |
257 | m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count); | 226 | uuidGatherer.GatherAll(); |
227 | |||
228 | m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", uuidGatherer.GatheredUuids.Count); | ||
258 | bool success = true; | 229 | bool success = true; |
259 | foreach (UUID uuid in ids.Keys) | 230 | foreach (UUID uuid in uuidGatherer.GatheredUuids.Keys) |
260 | if (FetchAsset(userAssetURL, uuid) == null) | 231 | if (FetchAsset(userAssetURL, uuid) == null) |
261 | success = false; | 232 | success = false; |
262 | 233 | ||
@@ -267,39 +238,92 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
267 | m_log.DebugFormat("[HG ASSET MAPPER]: Successfully got item {0} from asset server {1}", assetID, userAssetURL); | 238 | m_log.DebugFormat("[HG ASSET MAPPER]: Successfully got item {0} from asset server {1}", assetID, userAssetURL); |
268 | } | 239 | } |
269 | 240 | ||
270 | |||
271 | public void Post(UUID assetID, UUID ownerID, string userAssetURL) | 241 | public void Post(UUID assetID, UUID ownerID, string userAssetURL) |
272 | { | 242 | { |
273 | // Post the item from the local AssetCache onto the remote asset server | 243 | m_log.DebugFormat("[HG ASSET MAPPER]: Starting to send asset {0} with children to asset server {1}", assetID, userAssetURL); |
274 | // and place an entry in m_assetMap | 244 | |
245 | // Find all the embedded assets | ||
275 | 246 | ||
276 | m_log.Debug("[HG ASSET MAPPER]: Posting object " + assetID + " to asset server " + userAssetURL); | ||
277 | AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); | 247 | AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); |
278 | if (asset != null) | 248 | if (asset == null) |
249 | { | ||
250 | m_log.DebugFormat("[HG ASSET MAPPER]: Something wrong with asset {0}, it could not be found", assetID); | ||
251 | return; | ||
252 | } | ||
253 | |||
254 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); | ||
255 | uuidGatherer.AddForInspection(asset.FullID); | ||
256 | uuidGatherer.GatherAll(); | ||
257 | |||
258 | // Check which assets already exist in the destination server | ||
259 | |||
260 | string url = userAssetURL; | ||
261 | if (!url.EndsWith("/") && !url.EndsWith("=")) | ||
262 | url = url + "/"; | ||
263 | |||
264 | string[] remoteAssetIDs = new string[uuidGatherer.GatheredUuids.Count]; | ||
265 | int i = 0; | ||
266 | foreach (UUID id in uuidGatherer.GatheredUuids.Keys) | ||
267 | remoteAssetIDs[i++] = url + id.ToString(); | ||
268 | |||
269 | bool[] exist = m_scene.AssetService.AssetsExist(remoteAssetIDs); | ||
270 | |||
271 | var existSet = new HashSet<string>(); | ||
272 | i = 0; | ||
273 | foreach (UUID id in uuidGatherer.GatheredUuids.Keys) | ||
274 | { | ||
275 | if (exist[i]) | ||
276 | existSet.Add(id.ToString()); | ||
277 | ++i; | ||
278 | } | ||
279 | |||
280 | // Send only those assets which don't already exist in the destination server | ||
281 | |||
282 | bool success = true; | ||
283 | |||
284 | foreach (UUID uuid in uuidGatherer.GatheredUuids.Keys) | ||
279 | { | 285 | { |
280 | Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); | 286 | if (!existSet.Contains(uuid.ToString())) |
281 | HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); | ||
282 | uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); | ||
283 | bool success = false; | ||
284 | foreach (UUID uuid in ids.Keys) | ||
285 | { | 287 | { |
286 | asset = m_scene.AssetService.Get(uuid.ToString()); | 288 | asset = m_scene.AssetService.Get(uuid.ToString()); |
287 | if (asset == null) | 289 | if (asset == null) |
290 | { | ||
288 | m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid); | 291 | m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid); |
292 | } | ||
289 | else | 293 | else |
290 | success = PostAsset(userAssetURL, asset); | 294 | { |
295 | try | ||
296 | { | ||
297 | success &= PostAsset(userAssetURL, asset); | ||
298 | } | ||
299 | catch (Exception e) | ||
300 | { | ||
301 | m_log.Error( | ||
302 | string.Format( | ||
303 | "[HG ASSET MAPPER]: Failed to post asset {0} (type {1}, length {2}) referenced from {3} to {4} with exception ", | ||
304 | asset.ID, asset.Type, asset.Data.Length, assetID, userAssetURL), | ||
305 | e); | ||
306 | |||
307 | // For debugging purposes for now we will continue to throw the exception up the stack as was already happening. However, after | ||
308 | // debugging we may want to simply report the failure if we can tell this is due to a failure | ||
309 | // with a particular asset and not a destination network failure where all asset posts will fail (and | ||
310 | // generate large amounts of log spam). | ||
311 | throw e; | ||
312 | } | ||
313 | } | ||
291 | } | 314 | } |
292 | |||
293 | // maybe all pieces got there... | ||
294 | if (!success) | ||
295 | m_log.DebugFormat("[HG ASSET MAPPER]: Problems posting item {0} to asset server {1}", assetID, userAssetURL); | ||
296 | else | 315 | else |
297 | m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL); | 316 | { |
298 | 317 | m_log.DebugFormat( | |
318 | "[HG ASSET MAPPER]: Didn't post asset {0} referenced from {1} because it already exists in asset server {2}", | ||
319 | uuid, assetID, userAssetURL); | ||
320 | } | ||
299 | } | 321 | } |
300 | else | ||
301 | m_log.DebugFormat("[HG ASSET MAPPER]: Something wrong with asset {0}, it could not be found", assetID); | ||
302 | 322 | ||
323 | if (!success) | ||
324 | m_log.DebugFormat("[HG ASSET MAPPER]: Problems sending asset {0} with children to asset server {1}", assetID, userAssetURL); | ||
325 | else | ||
326 | m_log.DebugFormat("[HG ASSET MAPPER]: Successfully sent asset {0} with children to asset server {1}", assetID, userAssetURL); | ||
303 | } | 327 | } |
304 | 328 | ||
305 | #endregion | 329 | #endregion |