From 4c2171ec827aa426375ccecf4bd2d7e009719d74 Mon Sep 17 00:00:00 2001
From: Justin Clarke Casey
Date: Mon, 16 Jun 2008 21:59:39 +0000
Subject: * Allow archiver to save and load objects within other objects to
arbitrary levels * This currently has various bugs which are more to do with
the way its been hacked together than the feature itself (e.g. on save-oar,
ghost prims will appear of the saved contained items). These will be found
and eliminated in subsequent patches. * Not yet ready for use
---
.../Archiver/ArchiveWriteRequestPreparation.cs | 130 ++++++++++++++++-----
1 file changed, 99 insertions(+), 31 deletions(-)
(limited to 'OpenSim/Region/Environment/Modules/World')
diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestPreparation.cs
index a93e58d..1b78f4c 100644
--- a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestPreparation.cs
+++ b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequestPreparation.cs
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
@@ -47,64 +47,132 @@ namespace OpenSim.Region.Environment.Modules.World.Archiver
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected Scene m_scene;
- protected string m_savePath;
+ protected string m_savePath;
+
+ ///
+ /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate
+ /// asset was found by the asset service.
+ ///
+ protected AssetBase m_requestedObjectAsset;
+
+ ///
+ /// Signal whether we are currently waiting for the asset service to deliver an asset.
+ ///
+ protected bool m_waitingForObjectAsset;
+ ///
+ /// Constructor
+ ///
public ArchiveWriteRequestPreparation(Scene scene, string savePath)
{
m_scene = scene;
m_savePath = savePath;
}
-
- public void ArchiveRegion()
+
+ ///
+ /// The callback made when we request the asset for an object from the asset service.
+ ///
+ public void AssetRequestCallback(LLUUID assetID, AssetBase asset)
{
- Dictionary assetUuids = new Dictionary();
-
- List entities = m_scene.GetEntities();
-
- foreach (EntityBase entity in entities)
+ lock (this)
{
- if (entity is SceneObjectGroup)
+ m_requestedObjectAsset = asset;
+ m_waitingForObjectAsset = false;
+ Monitor.Pulse(this);
+ }
+ }
+
+ ///
+ /// Get all the asset uuids associated with a given object. This includes both those directly associated with
+ /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained
+ /// within this object).
+ ///
+ ///
+ ///
+ protected void GetSceneObjectAssetUuids(SceneObjectGroup sceneObject, IDictionary assetUuids)
+ {
+ m_log.DebugFormat(
+ "[ARCHIVER]: Getting assets for object {0}, {1}", sceneObject.RootPart.Name, sceneObject.UUID);
+
+ foreach (SceneObjectPart part in sceneObject.GetParts())
+ {
+ m_log.DebugFormat(
+ "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID);
+
+ // XXX: Not a great way to iterate through face textures, but there's no
+ // other way to tell how many faces there actually are
+ int i = 0;
+ foreach (LLObject.TextureEntryFace texture in part.Shape.Textures.FaceTextures)
{
- SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
+ if (texture != null)
+ {
+ m_log.DebugFormat("[ARCHIVER]: Got face {0}", i++);
+ assetUuids[texture.TextureID] = 1;
+ }
+ }
- foreach (SceneObjectPart part in sceneObject.GetParts())
+ foreach (TaskInventoryItem tii in part.TaskInventory.Values)
+ {
+ if (!assetUuids.ContainsKey(tii.AssetID))
{
- // XXX: Not a great way to iterate through face textures, but there's no
- // other way to tell how many faces there actually are
- //int i = 0;
- foreach (LLObject.TextureEntryFace texture in part.Shape.Textures.FaceTextures)
+ assetUuids[tii.AssetID] = 1;
+
+ if (tii.Type != (int)InventoryType.Object)
{
- if (texture != null)
- {
- //m_log.DebugFormat("[ARCHIVER]: Got face {0}", i++);
- assetUuids[texture.TextureID] = 1;
- }
+ m_log.DebugFormat("[ARCHIVER]: Recording asset {0} in object {1}", tii.AssetID, part.UUID);
}
-
- foreach (TaskInventoryItem tit in part.TaskInventory.Values)
+ else
{
- if (tit.Type != (int)InventoryType.Object)
+ m_waitingForObjectAsset = true;
+ m_scene.AssetCache.GetAsset(tii.AssetID, AssetRequestCallback, true);
+
+ // The asset cache callback can either
+ //
+ // 1. Complete on the same thread (if the asset is already in the cache) or
+ // 2. Come in via a different thread (if we need to go fetch it).
+ //
+ // The code below handles both these alternatives.
+ lock (this)
{
- m_log.DebugFormat("[ARCHIVER]: Recording asset {0} in object {1}", tit.AssetID, part.UUID);
- assetUuids[tit.AssetID] = 1;
+ if (m_waitingForObjectAsset)
+ {
+ Monitor.Wait(this);
+ m_waitingForObjectAsset = false;
+ }
}
- else
+
+ if (null != m_requestedObjectAsset)
{
- // TODO: Need to unpack every tit and go through its textures & items, recursively
- // this will mean going through the 'assets' received multiple times so that we can
- // unpack objects within objects before recursively requesting the inner assets
+ string xml = Helpers.FieldToUTF8String(m_requestedObjectAsset.Data);
+ SceneObjectGroup sog = new SceneObjectGroup(m_scene, m_scene.RegionInfo.RegionHandle, xml);
+ GetSceneObjectAssetUuids(sog, assetUuids);
}
}
}
}
}
+ }
+
+ public void ArchiveRegion()
+ {
+ Dictionary assetUuids = new Dictionary();
+
+ List entities = m_scene.GetEntities();
+
+ foreach (EntityBase entity in entities)
+ {
+ if (entity is SceneObjectGroup)
+ {
+ GetSceneObjectAssetUuids((SceneObjectGroup)entity, assetUuids);
+ }
+ }
string serializedEntities = SerializeObjects(entities);
if (serializedEntities != null && serializedEntities.Length > 0)
{
m_log.DebugFormat("[ARCHIVER]: Successfully got serialization for {0} entities", entities.Count);
- m_log.DebugFormat("[ARCHIVER]: Requiring save of {0} textures", assetUuids.Count);
+ m_log.DebugFormat("[ARCHIVER]: Requiring save of {0} assets", assetUuids.Count);
// Asynchronously request all the assets required to perform this archive operation
ArchiveWriteRequestExecution awre = new ArchiveWriteRequestExecution(serializedEntities, m_savePath);
--
cgit v1.1