aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Scenes/Hypergrid/HGAssetMapper.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Scenes/Hypergrid/HGAssetMapper.cs')
-rw-r--r--OpenSim/Region/Environment/Scenes/Hypergrid/HGAssetMapper.cs377
1 files changed, 377 insertions, 0 deletions
diff --git a/OpenSim/Region/Environment/Scenes/Hypergrid/HGAssetMapper.cs b/OpenSim/Region/Environment/Scenes/Hypergrid/HGAssetMapper.cs
new file mode 100644
index 0000000..3e27b7c
--- /dev/null
+++ b/OpenSim/Region/Environment/Scenes/Hypergrid/HGAssetMapper.cs
@@ -0,0 +1,377 @@
1/**
2 * Copyright (c) 2008, Contributors. All rights reserved.
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the Organizations nor the names of Individual
14 * Contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
25 * OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29using System;
30using System.Collections;
31using System.Collections.Generic;
32using System.Reflection;
33using System.Threading;
34
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38
39using OpenSim.Framework;
40using OpenSim.Framework.Communications;
41using OpenSim.Framework.Communications.Cache;
42using OpenSim.Framework.Servers;
43using OpenSim.Region.Environment;
44using OpenSim.Region.Environment.Scenes;
45
46//using HyperGrid.Framework;
47//using OpenSim.Region.Communications.Hypergrid;
48
49namespace OpenSim.Region.Environment.Scenes.Hypergrid
50{
51 public class HGAssetMapper
52 {
53 #region Fields
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 // This maps between asset server URLs and asset server clients
57 private Dictionary<string, GridAssetClient> m_assetServers = new Dictionary<string, GridAssetClient>();
58
59 // This maps between asset UUIDs and asset servers
60 private Dictionary<UUID, GridAssetClient> m_assetMap = new Dictionary<UUID, GridAssetClient>();
61
62 private Scene m_scene;
63 #endregion
64
65 #region Constructor
66
67 public HGAssetMapper(Scene scene)
68 {
69 m_scene = scene;
70 }
71
72 #endregion
73
74 #region Internal functions
75
76 private string UserAssetURL(UUID userID)
77 {
78 CachedUserInfo uinfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(userID);
79 if (uinfo != null)
80 return (uinfo.UserProfile.UserAssetURI == "") ? null : uinfo.UserProfile.UserAssetURI;
81 return null;
82 }
83
84 private bool IsHomeUser(UUID userID)
85 {
86 CachedUserInfo uinfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(userID);
87
88 if (uinfo != null)
89 {
90 //if ((uinfo.UserProfile.UserAssetURI == null) || (uinfo.UserProfile.UserAssetURI == "") ||
91 // uinfo.UserProfile.UserAssetURI.Equals(m_scene.CommsManager.NetworkServersInfo.AssetURL))
92 if (HGNetworkServersInfo.Singleton.IsLocalUser(uinfo.UserProfile.UserAssetURI))
93 {
94 m_log.Debug("[HGScene]: Home user " + uinfo.UserProfile.FirstName + " " + uinfo.UserProfile.SurName);
95 return true;
96 }
97 }
98
99 m_log.Debug("[HGScene]: Foreign user " + uinfo.UserProfile.FirstName + " " + uinfo.UserProfile.SurName);
100 return false;
101 }
102
103 private bool IsInAssetMap(UUID uuid)
104 {
105 return m_assetMap.ContainsKey(uuid);
106 }
107
108 private bool FetchAsset(GridAssetClient asscli, UUID assetID, bool isTexture)
109 {
110 // I'm not going over 3 seconds since this will be blocking processing of all the other inbound
111 // packets from the client.
112 int pollPeriod = 200;
113 int maxPolls = 15;
114
115 AssetBase asset;
116
117 // Maybe it came late, and it's already here. Check first.
118 if (m_scene.CommsManager.AssetCache.TryGetCachedAsset(assetID, out asset))
119 {
120 m_log.Debug("[HGScene]: Asset already in asset cache. " + assetID);
121 return true;
122 }
123
124
125 asscli.RequestAsset(assetID, isTexture);
126
127 do
128 {
129 Thread.Sleep(pollPeriod);
130
131 if (m_scene.CommsManager.AssetCache.TryGetCachedAsset(assetID, out asset) && (asset != null))
132 {
133 m_log.Debug("[HGScene]: Asset made it to asset cache. " + asset.Name + " " + assetID);
134 // I think I need to store it in the asset DB too.
135 // For now, let me just do it for textures and scripts
136 if (((AssetType)asset.Type == AssetType.Texture) ||
137 ((AssetType)asset.Type == AssetType.LSLBytecode) ||
138 ((AssetType)asset.Type == AssetType.LSLText))
139 {
140 AssetBase asset1 = new AssetBase();
141 Copy(asset, asset1);
142 m_scene.AssetCache.AssetServer.StoreAsset(asset1);
143 }
144 return true;
145 }
146 } while (--maxPolls > 0);
147
148 m_log.WarnFormat("[HGScene]: {0} {1} was not received before the retrieval timeout was reached",
149 isTexture ? "texture" : "asset", assetID.ToString());
150
151 return false;
152 }
153
154 private bool PostAsset(GridAssetClient asscli, UUID assetID)
155 {
156 AssetBase asset1;
157 m_scene.CommsManager.AssetCache.TryGetCachedAsset(assetID, out asset1);
158
159 if (asset1 != null)
160 {
161 // See long comment in AssetCache.AddAsset
162 if (!asset1.Temporary || asset1.Local)
163 {
164 // The asset cache returns instances of subclasses of AssetBase:
165 // TextureImage or AssetInfo. So in passing them to the remote
166 // server we first need to convert this to instances of AssetBase,
167 // which is the serializable class for assets.
168 AssetBase asset = new AssetBase();
169 Copy(asset1, asset);
170
171 asscli.StoreAsset(asset);
172 }
173 return true;
174 }
175 else
176 m_log.Warn("[HGScene]: Tried to post asset to remote server, but asset not in local cache.");
177
178 return false;
179 }
180
181 private void Copy(AssetBase from, AssetBase to)
182 {
183 to.Data = from.Data;
184 to.Description = from.Description;
185 to.FullID = from.FullID;
186 to.ID = from.ID;
187 to.Local = from.Local;
188 to.Name = from.Name;
189 to.Temporary = from.Temporary;
190 to.Type = from.Type;
191
192 }
193
194 private void _guardedAdd(Dictionary<UUID, bool> lst, UUID obj, bool val)
195 {
196 if (!lst.ContainsKey(obj))
197 lst.Add(obj, val);
198 }
199
200 private void SniffTextureUUIDs(Dictionary<UUID, bool> uuids, SceneObjectGroup sog)
201 {
202 try
203 {
204 _guardedAdd(uuids, sog.RootPart.Shape.Textures.DefaultTexture.TextureID, true);
205 }
206 catch (Exception) { }
207
208 foreach (Primitive.TextureEntryFace tface in sog.RootPart.Shape.Textures.FaceTextures)
209 {
210 try
211 {
212 _guardedAdd(uuids, tface.TextureID, true);
213 }
214 catch (Exception) { }
215 }
216
217 foreach (SceneObjectPart sop in sog.Children.Values)
218 {
219 try
220 {
221 _guardedAdd(uuids, sop.Shape.Textures.DefaultTexture.TextureID, true);
222 }
223 catch (Exception) { }
224 foreach (Primitive.TextureEntryFace tface in sop.Shape.Textures.FaceTextures)
225 {
226 try
227 {
228 _guardedAdd(uuids, tface.TextureID, true);
229 }
230 catch (Exception) { }
231 }
232 }
233 }
234
235 private void SniffTaskInventoryUUIDs(Dictionary<UUID, bool> uuids, SceneObjectGroup sog)
236 {
237 TaskInventoryDictionary tinv = sog.RootPart.TaskInventory;
238
239 foreach (TaskInventoryItem titem in tinv.Values)
240 {
241 uuids.Add(titem.AssetID, (InventoryType)titem.Type == InventoryType.Texture);
242 }
243 }
244
245 private Dictionary<UUID, bool> SniffUUIDs(AssetBase asset)
246 {
247 Dictionary<UUID, bool> uuids = new Dictionary<UUID, bool>();
248 if ((asset != null) && ((AssetType)asset.Type == AssetType.Object))
249 {
250 string ass_str = Utils.BytesToString(asset.Data);
251 SceneObjectGroup sog = new SceneObjectGroup(ass_str, true);
252
253 SniffTextureUUIDs(uuids, sog);
254
255 // We need to sniff further...
256 SniffTaskInventoryUUIDs(uuids, sog);
257
258 }
259
260 return uuids;
261 }
262
263 private Dictionary<UUID, bool> SniffUUIDs(UUID assetID)
264 {
265 Dictionary<UUID, bool> uuids = new Dictionary<UUID, bool>();
266
267 AssetBase asset;
268 m_scene.CommsManager.AssetCache.TryGetCachedAsset(assetID, out asset);
269
270 return SniffUUIDs(asset);
271 }
272
273 private void Dump(Dictionary<UUID, bool> lst)
274 {
275 m_log.Debug("XXX -------- UUID DUMP ------- XXX");
276 foreach (KeyValuePair<UUID, bool> kvp in lst)
277 m_log.Debug(" >> " + kvp.Key + " (texture? " + kvp.Value + ")");
278 m_log.Debug("XXX -------- UUID DUMP ------- XXX");
279 }
280
281 #endregion
282
283
284 #region Public interface
285
286 public void Get(UUID itemID, UUID ownerID)
287 {
288 if (!IsInAssetMap(itemID) && !IsHomeUser(ownerID))
289 {
290 // Get the item from the remote asset server onto the local AssetCache
291 // and place an entry in m_assetMap
292
293 GridAssetClient asscli = null;
294 string userAssetURL = UserAssetURL(ownerID);
295 if (userAssetURL != null)
296 {
297 m_assetServers.TryGetValue(userAssetURL, out asscli);
298 if (asscli == null)
299 {
300 m_log.Debug("[HGScene]: Starting new GridAssetClient for " + userAssetURL);
301 asscli = new GridAssetClient(userAssetURL);
302 asscli.SetReceiver(m_scene.CommsManager.AssetCache); // Straight to the asset cache!
303 m_assetServers.Add(userAssetURL, asscli);
304 }
305
306 m_log.Debug("[HGScene]: Fetching object " + itemID + " to asset server " + userAssetURL);
307 bool success = FetchAsset(asscli, itemID, false); // asscli.RequestAsset(item.ItemID, false);
308
309 // OK, now fetch the inside.
310 Dictionary<UUID, bool> ids = SniffUUIDs(itemID);
311 Dump(ids);
312 foreach (KeyValuePair<UUID, bool> kvp in ids)
313 FetchAsset(asscli, kvp.Key, kvp.Value);
314
315
316 if (success)
317 {
318 m_log.Debug("[HGScene]: Successfully fetched item from remote asset server " + userAssetURL);
319 m_assetMap.Add(itemID, asscli);
320 }
321 else
322 m_log.Warn("[HGScene]: Could not fetch asset from remote asset server " + userAssetURL);
323 }
324 else
325 m_log.Warn("[HGScene]: Unable to locate foreign user's asset server");
326 }
327 }
328
329 public void Post(UUID itemID, UUID ownerID)
330 {
331 if (!IsHomeUser(ownerID))
332 {
333 // Post the item from the local AssetCache ontp the remote asset server
334 // and place an entry in m_assetMap
335
336 GridAssetClient asscli = null;
337 string userAssetURL = UserAssetURL(ownerID);
338 if (userAssetURL != null)
339 {
340 m_assetServers.TryGetValue(userAssetURL, out asscli);
341 if (asscli == null)
342 {
343 m_log.Debug("[HGScene]: Starting new GridAssetClient for " + userAssetURL);
344 asscli = new GridAssetClient(userAssetURL);
345 asscli.SetReceiver(m_scene.CommsManager.AssetCache); // Straight to the asset cache!
346 m_assetServers.Add(userAssetURL, asscli);
347 }
348 m_log.Debug("[HGScene]: Posting object " + itemID + " to asset server " + userAssetURL);
349 bool success = PostAsset(asscli, itemID);
350
351 // Now the inside
352 Dictionary<UUID, bool> ids = SniffUUIDs(itemID);
353 Dump(ids);
354 foreach (KeyValuePair<UUID, bool> kvp in ids)
355 PostAsset(asscli, kvp.Key);
356
357 if (success)
358 {
359 m_log.Debug("[HGScene]: Successfully posted item to remote asset server " + userAssetURL);
360 m_assetMap.Add(itemID, asscli);
361 }
362 else
363 m_log.Warn("[HGScene]: Could not post asset to remote asset server " + userAssetURL);
364
365 //if (!m_assetMap.ContainsKey(itemID))
366 // m_assetMap.Add(itemID, asscli);
367 }
368 else
369 m_log.Warn("[HGScene]: Unable to locate foreign user's asset server");
370
371 }
372 }
373
374 #endregion
375
376 }
377}