diff options
-rw-r--r-- | OpenSim/Region/Application/OpenSim.cs | 4 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs | 202 |
2 files changed, 121 insertions, 85 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 2c920f6..dd2e859 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs | |||
@@ -265,9 +265,9 @@ namespace OpenSim | |||
265 | LoadOar); | 265 | LoadOar); |
266 | 266 | ||
267 | m_console.Commands.AddCommand("region", false, "save oar", | 267 | m_console.Commands.AddCommand("region", false, "save oar", |
268 | "save oar [-v|version=N] [<OAR path>]", | 268 | "save oar [-v|--version=N] [<OAR path>]", |
269 | "Save a region's data to an OAR archive.", | 269 | "Save a region's data to an OAR archive.", |
270 | "-v|version=N generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine | 270 | "-v|--version=N generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine |
271 | + "The OAR path must be a filesystem path." | 271 | + "The OAR path must be a filesystem path." |
272 | + " If this is not given then the oar is saved to region.oar in the current directory.", | 272 | + " If this is not given then the oar is saved to region.oar in the current directory.", |
273 | SaveOar); | 273 | SaveOar); |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index 0567a82..3eb797b 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs | |||
@@ -49,7 +49,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
49 | public class ArchiveWriteRequestPreparation | 49 | public class ArchiveWriteRequestPreparation |
50 | { | 50 | { |
51 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 51 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
52 | 52 | ||
53 | /// <summary> | ||
54 | /// The minimum major version of OAR that we can write. | ||
55 | /// </summary> | ||
56 | public static int MIN_MAJOR_VERSION = 0; | ||
57 | |||
58 | /// <summary> | ||
59 | /// The maximum major version of OAR that we can write. | ||
60 | /// </summary> | ||
61 | public static int MAX_MAJOR_VERSION = 1; | ||
62 | |||
53 | protected Scene m_scene; | 63 | protected Scene m_scene; |
54 | protected Stream m_saveStream; | 64 | protected Stream m_saveStream; |
55 | protected Guid m_requestId; | 65 | protected Guid m_requestId; |
@@ -101,110 +111,136 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
101 | /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception> | 111 | /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception> |
102 | public void ArchiveRegion(Dictionary<string, object> options) | 112 | public void ArchiveRegion(Dictionary<string, object> options) |
103 | { | 113 | { |
104 | Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>(); | 114 | try |
105 | 115 | { | |
106 | EntityBase[] entities = m_scene.GetEntities(); | 116 | Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>(); |
107 | List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); | 117 | |
108 | 118 | EntityBase[] entities = m_scene.GetEntities(); | |
109 | /* | 119 | List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); |
110 | foreach (ILandObject lo in m_scene.LandChannel.AllParcels()) | 120 | |
121 | /* | ||
122 | foreach (ILandObject lo in m_scene.LandChannel.AllParcels()) | ||
123 | { | ||
124 | if (name == lo.LandData.Name) | ||
125 | { | ||
126 | // This is the parcel we want | ||
127 | } | ||
128 | } | ||
129 | */ | ||
130 | |||
131 | // Filter entities so that we only have scene objects. | ||
132 | // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods | ||
133 | // end up having to do this | ||
134 | foreach (EntityBase entity in entities) | ||
111 | { | 135 | { |
112 | if (name == lo.LandData.Name) | 136 | if (entity is SceneObjectGroup) |
113 | { | 137 | { |
114 | // This is the parcel we want | 138 | SceneObjectGroup sceneObject = (SceneObjectGroup)entity; |
139 | |||
140 | if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) | ||
141 | sceneObjects.Add((SceneObjectGroup)entity); | ||
115 | } | 142 | } |
116 | } | 143 | } |
117 | */ | 144 | |
118 | 145 | UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); | |
119 | // Filter entities so that we only have scene objects. | 146 | |
120 | // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods | 147 | foreach (SceneObjectGroup sceneObject in sceneObjects) |
121 | // end up having to do this | ||
122 | foreach (EntityBase entity in entities) | ||
123 | { | ||
124 | if (entity is SceneObjectGroup) | ||
125 | { | 148 | { |
126 | SceneObjectGroup sceneObject = (SceneObjectGroup)entity; | 149 | assetGatherer.GatherAssetUuids(sceneObject, assetUuids); |
127 | |||
128 | if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) | ||
129 | sceneObjects.Add((SceneObjectGroup)entity); | ||
130 | } | 150 | } |
151 | |||
152 | m_log.DebugFormat( | ||
153 | "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", | ||
154 | sceneObjects.Count, assetUuids.Count); | ||
155 | |||
156 | // Make sure that we also request terrain texture assets | ||
157 | RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; | ||
158 | |||
159 | if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) | ||
160 | assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; | ||
161 | |||
162 | if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) | ||
163 | assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; | ||
164 | |||
165 | if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) | ||
166 | assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; | ||
167 | |||
168 | if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) | ||
169 | assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; | ||
170 | |||
171 | TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream); | ||
172 | |||
173 | // Asynchronously request all the assets required to perform this archive operation | ||
174 | ArchiveWriteRequestExecution awre | ||
175 | = new ArchiveWriteRequestExecution( | ||
176 | sceneObjects, | ||
177 | m_scene.RequestModuleInterface<ITerrainModule>(), | ||
178 | m_scene.RequestModuleInterface<IRegionSerialiserModule>(), | ||
179 | m_scene, | ||
180 | archiveWriter, | ||
181 | m_requestId, | ||
182 | options); | ||
183 | |||
184 | m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time."); | ||
185 | |||
186 | // Write out control file. This has to be done first so that subsequent loaders will see this file first | ||
187 | // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this | ||
188 | archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options)); | ||
189 | m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); | ||
190 | |||
191 | new AssetsRequest( | ||
192 | new AssetsArchiver(archiveWriter), assetUuids, | ||
193 | m_scene.AssetService, awre.ReceivedAllAssets).Execute(); | ||
131 | } | 194 | } |
132 | 195 | finally | |
133 | UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); | ||
134 | |||
135 | foreach (SceneObjectGroup sceneObject in sceneObjects) | ||
136 | { | 196 | { |
137 | assetGatherer.GatherAssetUuids(sceneObject, assetUuids); | 197 | m_saveStream.Close(); |
138 | } | 198 | } |
139 | |||
140 | m_log.DebugFormat( | ||
141 | "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", | ||
142 | sceneObjects.Count, assetUuids.Count); | ||
143 | |||
144 | // Make sure that we also request terrain texture assets | ||
145 | RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; | ||
146 | |||
147 | if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) | ||
148 | assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; | ||
149 | |||
150 | if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) | ||
151 | assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; | ||
152 | |||
153 | if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) | ||
154 | assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; | ||
155 | |||
156 | if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) | ||
157 | assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; | ||
158 | |||
159 | TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream); | ||
160 | |||
161 | // Asynchronously request all the assets required to perform this archive operation | ||
162 | ArchiveWriteRequestExecution awre | ||
163 | = new ArchiveWriteRequestExecution( | ||
164 | sceneObjects, | ||
165 | m_scene.RequestModuleInterface<ITerrainModule>(), | ||
166 | m_scene.RequestModuleInterface<IRegionSerialiserModule>(), | ||
167 | m_scene, | ||
168 | archiveWriter, | ||
169 | m_requestId, | ||
170 | options); | ||
171 | |||
172 | m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time."); | ||
173 | |||
174 | // Write out control file. This has to be done first so that subsequent loaders will see this file first | ||
175 | // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this | ||
176 | archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p2ControlFile(options)); | ||
177 | m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); | ||
178 | |||
179 | new AssetsRequest( | ||
180 | new AssetsArchiver(archiveWriter), assetUuids, | ||
181 | m_scene.AssetService, awre.ReceivedAllAssets).Execute(); | ||
182 | } | 199 | } |
183 | 200 | ||
184 | /// <summary> | 201 | /// <summary> |
185 | /// Create the control file for the most up to date archive | 202 | /// Create the control file for the most up to date archive |
186 | /// </summary> | 203 | /// </summary> |
187 | /// <returns></returns> | 204 | /// <returns></returns> |
188 | public static string Create0p2ControlFile(Dictionary<string, object> options) | 205 | public static string CreateControlFile(Dictionary<string, object> options) |
189 | { | 206 | { |
190 | int majorVersion = 0, minorVersion = 5; | 207 | int majorVersion = MAX_MAJOR_VERSION, minorVersion = 0; |
191 | 208 | ||
192 | if (options.ContainsKey("version")) | 209 | if (options.ContainsKey("version")) |
193 | { | 210 | { |
194 | minorVersion = 0; | ||
195 | string[] parts = options["version"].ToString().Split('.'); | 211 | string[] parts = options["version"].ToString().Split('.'); |
196 | if (parts.Length >= 1) | 212 | if (parts.Length >= 1) |
197 | majorVersion = Int32.Parse(parts[0]); | 213 | { |
198 | if (parts.Length >= 2) | 214 | majorVersion = Int32.Parse(parts[0]); |
199 | minorVersion = Int32.Parse(parts[1]); | 215 | |
216 | if (parts.Length >= 2) | ||
217 | minorVersion = Int32.Parse(parts[1]); | ||
218 | } | ||
200 | } | 219 | } |
201 | 220 | ||
202 | m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); | 221 | if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION) |
203 | // if (majorVersion == 1) | 222 | { |
204 | // { | 223 | throw new Exception( |
205 | // m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR"); | 224 | string.Format( |
206 | // } | 225 | "OAR version number for save must be between {0} and {1}", |
226 | MIN_MAJOR_VERSION, MAX_MAJOR_VERSION)); | ||
227 | } | ||
228 | else if (majorVersion == MAX_MAJOR_VERSION) | ||
229 | { | ||
230 | // Force 1.0 | ||
231 | minorVersion = 0; | ||
232 | } | ||
233 | else if (majorVersion == MIN_MAJOR_VERSION) | ||
234 | { | ||
235 | // Force 0.4 | ||
236 | minorVersion = 4; | ||
237 | } | ||
207 | 238 | ||
239 | m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); | ||
240 | if (majorVersion == 1) | ||
241 | { | ||
242 | m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR"); | ||
243 | } | ||
208 | 244 | ||
209 | StringWriter sw = new StringWriter(); | 245 | StringWriter sw = new StringWriter(); |
210 | XmlTextWriter xtw = new XmlTextWriter(sw); | 246 | XmlTextWriter xtw = new XmlTextWriter(sw); |