aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequest.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequest.cs')
-rw-r--r--OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequest.cs210
1 files changed, 210 insertions, 0 deletions
diff --git a/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequest.cs
new file mode 100644
index 0000000..b952200
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/World/Archiver/ArchiveWriteRequest.cs
@@ -0,0 +1,210 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using OpenSim.Framework;
29using OpenSim.Framework.Communications.Cache;
30using OpenSim.Region.Environment.Interfaces;
31using OpenSim.Region.Environment.Modules.World.Serialiser;
32using OpenSim.Region.Environment.Scenes;
33using System.Collections.Generic;
34using System.Reflection;
35using libsecondlife;
36using log4net;
37using Nini.Config;
38
39namespace OpenSim.Region.Environment
40{
41 /// <summary>
42 /// Method called when all the necessary assets for an archive request have been received.
43 /// </summary>
44 public delegate void AssetsRequestCallback(IDictionary<LLUUID, AssetBase> assets);
45
46 /// <summary>
47 /// Handles an individual archive write request
48 /// </summary>
49 public class ArchiveWriteRequest
50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 private Scene m_scene;
54 private string m_savePath;
55
56 private string m_serializedEntities;
57
58 public ArchiveWriteRequest(Scene scene, string savePath)
59 {
60 m_scene = scene;
61 m_savePath = savePath;
62
63 ArchiveRegion();
64 }
65
66 protected void ArchiveRegion()
67 {
68 Dictionary<LLUUID, int> textureUuids = new Dictionary<LLUUID, int>();
69
70 List<EntityBase> entities = m_scene.GetEntities();
71
72 foreach (EntityBase entity in entities)
73 {
74 if (entity is SceneObjectGroup)
75 {
76 SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
77
78 foreach (SceneObjectPart part in sceneObject.GetParts())
79 {
80 LLUUID texture = new LLUUID(part.Shape.TextureEntry, 0);
81 textureUuids[texture] = 1;
82 }
83 }
84 }
85
86 m_serializedEntities = SerializeObjects(entities);
87
88 if (m_serializedEntities != null && m_serializedEntities.Length > 0)
89 {
90 m_log.DebugFormat("[ARCHIVER]: Successfully got serialization for {0} entities", entities.Count);
91 m_log.DebugFormat("[ARCHIVER]: Requiring save of {0} textures", textureUuids.Count);
92
93 // Asynchronously request all the assets required to perform this archive operation
94 new AssetsRequest(ReceivedAllAssets, m_scene.AssetCache, textureUuids.Keys);
95 }
96 }
97
98 protected internal void ReceivedAllAssets(IDictionary<LLUUID, AssetBase> assets)
99 {
100 m_log.DebugFormat("[ARCHIVER]: Received all {0} textures required", assets.Count);
101
102 // XXX: Shouldn't hijack the asset async callback thread like this - this is only temporary
103
104 TarArchiveWriter archive = new TarArchiveWriter();
105
106 archive.AddFile("prims.xml", m_serializedEntities);
107
108 // It appears that gtar, at least, doesn't need the intermediate directory entries in the tar
109 //archive.AddDir("assets");
110
111 foreach (LLUUID uuid in assets.Keys)
112 {
113 if (assets[uuid] != null)
114 {
115 archive.AddFile("assets/" + uuid.ToString() + ".jp2", assets[uuid].Data);
116 }
117 else
118 {
119 m_log.DebugFormat("[ARCHIVER]: Could not find asset {0} to archive", uuid);
120 }
121 }
122
123 archive.WriteTar(m_savePath);
124 }
125
126 /// <summary>
127 /// Get an xml representation of the given scene objects.
128 /// </summary>
129 /// <param name="scene"></param>
130 /// <returns></returns>
131 protected static string SerializeObjects(List<EntityBase> entities)
132 {
133 string serialization = "<scene>";
134
135 List<string> serObjects = new List<string>();
136
137 foreach (EntityBase ent in entities)
138 {
139 if (ent is SceneObjectGroup)
140 {
141 serObjects.Add(((SceneObjectGroup) ent).ToXmlString2());
142 }
143 }
144
145 foreach (string serObject in serObjects)
146 serialization += serObject;
147
148 serialization += "</scene>";
149
150 return serialization;
151 }
152 }
153
154 /// <summary>
155 /// Encapsulate the asynchronous requests for the assets required for an archive operation
156 /// </summary>
157 class AssetsRequest
158 {
159 /// <summary>
160 /// Callback used when all the assets requested have been received.
161 /// </summary>
162 protected AssetsRequestCallback m_assetsRequestCallback;
163
164 /// <summary>
165 /// Assets retrieved in this request
166 /// </summary>
167 protected Dictionary<LLUUID, AssetBase> m_assets = new Dictionary<LLUUID, AssetBase>();
168
169 /// <summary>
170 /// Record the number of asset replies required so we know when we've finished
171 /// </summary>
172 private int m_repliesRequired;
173
174 /// <summary>
175 /// Asset cache used to request the assets
176 /// </summary>
177 protected AssetCache m_assetCache;
178
179 protected internal AssetsRequest(AssetsRequestCallback assetsRequestCallback, AssetCache assetCache, ICollection<LLUUID> uuids)
180 {
181 m_assetsRequestCallback = assetsRequestCallback;
182 m_assetCache = assetCache;
183 m_repliesRequired = uuids.Count;
184
185 // We can stop here if there are no assets to fetch
186 if (m_repliesRequired == 0)
187 m_assetsRequestCallback(m_assets);
188
189 foreach (LLUUID uuid in uuids)
190 {
191 m_assetCache.GetAsset(uuid, AssetRequestCallback, true);
192 }
193 }
194
195 /// <summary>
196 /// Called back by the asset cache when it has the asset
197 /// </summary>
198 /// <param name="assetID"></param>
199 /// <param name="asset"></param>
200 public void AssetRequestCallback(LLUUID assetID, AssetBase asset)
201 {
202 m_assets[assetID] = asset;
203
204 if (m_assets.Count == m_repliesRequired)
205 {
206 m_assetsRequestCallback(m_assets);
207 }
208 }
209 }
210}