aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs376
1 files changed, 376 insertions, 0 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs b/OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs
new file mode 100644
index 0000000..bd9c260
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs
@@ -0,0 +1,376 @@
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;
43// using OpenSim.Region.Environment;
44using OpenSim.Region.Framework.Scenes;
45
46//using HyperGrid.Framework;
47//using OpenSim.Region.Communications.Hypergrid;
48
49namespace OpenSim.Region.Framework.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 IsLocalUser(UUID userID)
85 {
86 CachedUserInfo uinfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(userID);
87
88 if (uinfo != null)
89 {
90 if (HGNetworkServersInfo.Singleton.IsLocalUser(uinfo.UserProfile))
91 {
92 m_log.Debug("[HGScene]: Home user " + uinfo.UserProfile.FirstName + " " + uinfo.UserProfile.SurName);
93 return true;
94 }
95 }
96
97 m_log.Debug("[HGScene]: Foreign user " + uinfo.UserProfile.FirstName + " " + uinfo.UserProfile.SurName);
98 return false;
99 }
100
101 private bool IsInAssetMap(UUID uuid)
102 {
103 return m_assetMap.ContainsKey(uuid);
104 }
105
106 private bool FetchAsset(GridAssetClient asscli, UUID assetID, bool isTexture)
107 {
108 // I'm not going over 3 seconds since this will be blocking processing of all the other inbound
109 // packets from the client.
110 int pollPeriod = 200;
111 int maxPolls = 15;
112
113 AssetBase asset;
114
115 // Maybe it came late, and it's already here. Check first.
116 if (m_scene.CommsManager.AssetCache.TryGetCachedAsset(assetID, out asset))
117 {
118 m_log.Debug("[HGScene]: Asset already in asset cache. " + assetID);
119 return true;
120 }
121
122
123 asscli.RequestAsset(assetID, isTexture);
124
125 do
126 {
127 Thread.Sleep(pollPeriod);
128
129 if (m_scene.CommsManager.AssetCache.TryGetCachedAsset(assetID, out asset) && (asset != null))
130 {
131 m_log.Debug("[HGScene]: Asset made it to asset cache. " + asset.Metadata.Name + " " + assetID);
132 // I think I need to store it in the asset DB too.
133 // For now, let me just do it for textures and scripts
134 if (((AssetType)asset.Metadata.Type == AssetType.Texture) ||
135 ((AssetType)asset.Metadata.Type == AssetType.LSLBytecode) ||
136 ((AssetType)asset.Metadata.Type == AssetType.LSLText))
137 {
138 AssetBase asset1 = new AssetBase();
139 Copy(asset, asset1);
140 m_scene.AssetCache.AssetServer.StoreAsset(asset1);
141 }
142 return true;
143 }
144 } while (--maxPolls > 0);
145
146 m_log.WarnFormat("[HGScene]: {0} {1} was not received before the retrieval timeout was reached",
147 isTexture ? "texture" : "asset", assetID.ToString());
148
149 return false;
150 }
151
152 private bool PostAsset(GridAssetClient asscli, UUID assetID)
153 {
154 AssetBase asset1;
155 m_scene.CommsManager.AssetCache.TryGetCachedAsset(assetID, out asset1);
156
157 if (asset1 != null)
158 {
159 // See long comment in AssetCache.AddAsset
160 if (!asset1.Metadata.Temporary || asset1.Metadata.Local)
161 {
162 // The asset cache returns instances of subclasses of AssetBase:
163 // TextureImage or AssetInfo. So in passing them to the remote
164 // server we first need to convert this to instances of AssetBase,
165 // which is the serializable class for assets.
166 AssetBase asset = new AssetBase();
167 Copy(asset1, asset);
168
169 asscli.StoreAsset(asset);
170 }
171 return true;
172 }
173 else
174 m_log.Warn("[HGScene]: Tried to post asset to remote server, but asset not in local cache.");
175
176 return false;
177 }
178
179 private void Copy(AssetBase from, AssetBase to)
180 {
181 to.Data = from.Data;
182 to.Metadata.Description = from.Metadata.Description;
183 to.Metadata.FullID = from.Metadata.FullID;
184 to.Metadata.ID = from.Metadata.ID;
185 to.Metadata.Local = from.Metadata.Local;
186 to.Metadata.Name = from.Metadata.Name;
187 to.Metadata.Temporary = from.Metadata.Temporary;
188 to.Metadata.Type = from.Metadata.Type;
189
190 }
191
192 private void _guardedAdd(Dictionary<UUID, bool> lst, UUID obj, bool val)
193 {
194 if (!lst.ContainsKey(obj))
195 lst.Add(obj, val);
196 }
197
198 private void SniffTextureUUIDs(Dictionary<UUID, bool> uuids, SceneObjectGroup sog)
199 {
200 try
201 {
202 _guardedAdd(uuids, sog.RootPart.Shape.Textures.DefaultTexture.TextureID, true);
203 }
204 catch (Exception) { }
205
206 foreach (Primitive.TextureEntryFace tface in sog.RootPart.Shape.Textures.FaceTextures)
207 {
208 try
209 {
210 _guardedAdd(uuids, tface.TextureID, true);
211 }
212 catch (Exception) { }
213 }
214
215 foreach (SceneObjectPart sop in sog.Children.Values)
216 {
217 try
218 {
219 _guardedAdd(uuids, sop.Shape.Textures.DefaultTexture.TextureID, true);
220 }
221 catch (Exception) { }
222 foreach (Primitive.TextureEntryFace tface in sop.Shape.Textures.FaceTextures)
223 {
224 try
225 {
226 _guardedAdd(uuids, tface.TextureID, true);
227 }
228 catch (Exception) { }
229 }
230 }
231 }
232
233 private void SniffTaskInventoryUUIDs(Dictionary<UUID, bool> uuids, SceneObjectGroup sog)
234 {
235 TaskInventoryDictionary tinv = sog.RootPart.TaskInventory;
236
237 foreach (TaskInventoryItem titem in tinv.Values)
238 {
239 uuids.Add(titem.AssetID, (InventoryType)titem.Type == InventoryType.Texture);
240 }
241 }
242
243 private Dictionary<UUID, bool> SniffUUIDs(AssetBase asset)
244 {
245 Dictionary<UUID, bool> uuids = new Dictionary<UUID, bool>();
246 if ((asset != null) && ((AssetType)asset.Metadata.Type == AssetType.Object))
247 {
248 string ass_str = Utils.BytesToString(asset.Data);
249 SceneObjectGroup sog = new SceneObjectGroup(ass_str, true);
250
251 SniffTextureUUIDs(uuids, sog);
252
253 // We need to sniff further...
254 SniffTaskInventoryUUIDs(uuids, sog);
255
256 }
257
258 return uuids;
259 }
260
261 private Dictionary<UUID, bool> SniffUUIDs(UUID assetID)
262 {
263 //Dictionary<UUID, bool> uuids = new Dictionary<UUID, bool>();
264
265 AssetBase asset;
266 m_scene.CommsManager.AssetCache.TryGetCachedAsset(assetID, out asset);
267
268 return SniffUUIDs(asset);
269 }
270
271 private void Dump(Dictionary<UUID, bool> lst)
272 {
273 m_log.Debug("XXX -------- UUID DUMP ------- XXX");
274 foreach (KeyValuePair<UUID, bool> kvp in lst)
275 m_log.Debug(" >> " + kvp.Key + " (texture? " + kvp.Value + ")");
276 m_log.Debug("XXX -------- UUID DUMP ------- XXX");
277 }
278
279 #endregion
280
281
282 #region Public interface
283
284 public void Get(UUID itemID, UUID ownerID)
285 {
286 if (!IsInAssetMap(itemID) && !IsLocalUser(ownerID))
287 {
288 // Get the item from the remote asset server onto the local AssetCache
289 // and place an entry in m_assetMap
290
291 GridAssetClient asscli = null;
292 string userAssetURL = UserAssetURL(ownerID);
293 if (userAssetURL != null)
294 {
295 m_assetServers.TryGetValue(userAssetURL, out asscli);
296 if (asscli == null)
297 {
298 m_log.Debug("[HGScene]: Starting new GridAssetClient for " + userAssetURL);
299 asscli = new GridAssetClient(userAssetURL);
300 asscli.SetReceiver(m_scene.CommsManager.AssetCache); // Straight to the asset cache!
301 m_assetServers.Add(userAssetURL, asscli);
302 }
303
304 m_log.Debug("[HGScene]: Fetching object " + itemID + " to asset server " + userAssetURL);
305 bool success = FetchAsset(asscli, itemID, false); // asscli.RequestAsset(item.ItemID, false);
306
307 // OK, now fetch the inside.
308 Dictionary<UUID, bool> ids = SniffUUIDs(itemID);
309 Dump(ids);
310 foreach (KeyValuePair<UUID, bool> kvp in ids)
311 FetchAsset(asscli, kvp.Key, kvp.Value);
312
313
314 if (success)
315 {
316 m_log.Debug("[HGScene]: Successfully fetched item from remote asset server " + userAssetURL);
317 m_assetMap.Add(itemID, asscli);
318 }
319 else
320 m_log.Warn("[HGScene]: Could not fetch asset from remote asset server " + userAssetURL);
321 }
322 else
323 m_log.Warn("[HGScene]: Unable to locate foreign user's asset server");
324 }
325 }
326
327 public void Post(UUID itemID, UUID ownerID)
328 {
329 if (!IsLocalUser(ownerID))
330 {
331 // Post the item from the local AssetCache ontp the remote asset server
332 // and place an entry in m_assetMap
333
334 GridAssetClient asscli = null;
335 string userAssetURL = UserAssetURL(ownerID);
336 if (userAssetURL != null)
337 {
338 m_assetServers.TryGetValue(userAssetURL, out asscli);
339 if (asscli == null)
340 {
341 m_log.Debug("[HGScene]: Starting new GridAssetClient for " + userAssetURL);
342 asscli = new GridAssetClient(userAssetURL);
343 asscli.SetReceiver(m_scene.CommsManager.AssetCache); // Straight to the asset cache!
344 m_assetServers.Add(userAssetURL, asscli);
345 }
346 m_log.Debug("[HGScene]: Posting object " + itemID + " to asset server " + userAssetURL);
347 bool success = PostAsset(asscli, itemID);
348
349 // Now the inside
350 Dictionary<UUID, bool> ids = SniffUUIDs(itemID);
351 Dump(ids);
352 foreach (KeyValuePair<UUID, bool> kvp in ids)
353 PostAsset(asscli, kvp.Key);
354
355 if (success)
356 {
357 m_log.Debug("[HGScene]: Successfully posted item to remote asset server " + userAssetURL);
358 if (!m_assetMap.ContainsKey(itemID))
359 m_assetMap.Add(itemID, asscli);
360 }
361 else
362 m_log.Warn("[HGScene]: Could not post asset to remote asset server " + userAssetURL);
363
364 //if (!m_assetMap.ContainsKey(itemID))
365 // m_assetMap.Add(itemID, asscli);
366 }
367 else
368 m_log.Warn("[HGScene]: Unable to locate foreign user's asset server");
369
370 }
371 }
372
373 #endregion
374
375 }
376}