OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
ArchiverModule.cs
Go to the documentation of this file.
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 OpenSimulator 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 
28 using System;
29 using System.Collections.Generic;
30 using System.IO;
31 using System.Reflection;
32 using log4net;
33 using NDesk.Options;
34 using Nini.Config;
35 using Mono.Addins;
36 
37 using OpenSim.Framework;
38 using OpenSim.Framework.Console;
39 using OpenSim.Region.Framework.Interfaces;
40 using OpenSim.Region.Framework.Scenes;
41 
42 using OpenMetaverse;
43 
44 namespace OpenSim.Region.CoreModules.World.Archiver
45 {
49  [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ArchiverModule")]
51  {
52  private static readonly ILog m_log =
53  LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54 
55  public Scene Scene { get; private set; }
56  public IRegionCombinerModule RegionCombinerModule { get; private set; }
57 
61  protected const string DEFAULT_OAR_BACKUP_FILENAME = "region.oar";
62 
63  public string Name
64  {
65  get { return "RegionArchiverModule"; }
66  }
67 
68  public Type ReplaceableInterface
69  {
70  get { return null; }
71  }
72 
73 
74  public void Initialise(IConfigSource source)
75  {
76  //m_log.Debug("[ARCHIVER] Initialising");
77  }
78 
79  public void AddRegion(Scene scene)
80  {
81  Scene = scene;
82  Scene.RegisterModuleInterface<IRegionArchiverModule>(this);
83  //m_log.DebugFormat("[ARCHIVER]: Enabled for region {0}", scene.RegionInfo.RegionName);
84  }
85 
86  public void RegionLoaded(Scene scene)
87  {
88  RegionCombinerModule = scene.RequestModuleInterface<IRegionCombinerModule>();
89  }
90 
91  public void RemoveRegion(Scene scene)
92  {
93  }
94 
95  public void Close()
96  {
97  }
98 
103  public void HandleLoadOarConsoleCommand(string module, string[] cmdparams)
104  {
105  bool mergeOar = false;
106  bool skipAssets = false;
107  bool forceTerrain = false;
108  bool forceParcels = false;
109  bool noObjects = false;
110  Vector3 displacement = new Vector3(0f, 0f, 0f);
111  String defaultUser = "";
112  float rotation = 0f;
113  Vector3 rotationCenter = new Vector3(Scene.RegionInfo.RegionSizeX / 2f, Scene.RegionInfo.RegionSizeY / 2f, 0);
114  Vector3 boundingOrigin = new Vector3(0f, 0f, 0f);
115  Vector3 boundingSize = new Vector3(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY, float.MaxValue);
116  bool debug = false;
117 
118  OptionSet options = new OptionSet();
119  options.Add("m|merge", delegate(string v) { mergeOar = (v != null); });
120  options.Add("s|skip-assets", delegate(string v) { skipAssets = (v != null); });
121  options.Add("force-terrain", delegate(string v) { forceTerrain = (v != null); });
122  options.Add("forceterrain", delegate(string v) { forceTerrain = (v != null); }); // downward compatibility
123  options.Add("force-parcels", delegate(string v) { forceParcels = (v != null); });
124  options.Add("forceparcels", delegate(string v) { forceParcels = (v != null); }); // downward compatibility
125  options.Add("no-objects", delegate(string v) { noObjects = (v != null); });
126  options.Add("default-user=", delegate(string v) { defaultUser = (v == null) ? "" : v; });
127  options.Add("displacement=", delegate(string v)
128  {
129  try
130  {
131  displacement = v == null ? Vector3.Zero : Vector3.Parse(v);
132  }
133  catch
134  {
135  m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing displacement");
136  m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as vector3: --displacement \"<128,128,0>\"");
137  return;
138  }
139  });
140  options.Add("rotation=", delegate(string v)
141  {
142  try
143  {
144  rotation = v == null ? 0f : float.Parse(v);
145  }
146  catch
147  {
148  m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing rotation");
149  m_log.ErrorFormat("[ARCHIVER MODULE] Must be an angle in degrees between -360 and +360: --rotation 45");
150  return;
151  }
152  //pass this in as degrees now, convert to radians later during actual work phase
153  rotation = Util.Clamp<float>(rotation, -359f, 359f);
154  });
155  options.Add("rotation-center=", delegate(string v)
156  {
157  try
158  {
159  m_log.Info("[ARCHIVER MODULE] Warning: --rotation-center no longer does anything and will be removed soon!");
160  rotationCenter = v == null ? Vector3.Zero : Vector3.Parse(v);
161  }
162  catch
163  {
164  m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing rotation displacement");
165  m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as vector3: --rotation-center \"<128,128,0>\"");
166  return;
167  }
168  });
169  options.Add("bounding-origin=", delegate(string v)
170  {
171  try
172  {
173  boundingOrigin = v == null ? Vector3.Zero : Vector3.Parse(v);
174  }
175  catch
176  {
177  m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing bounding cube origin");
178  m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as vector3: --bounding-origin \"<128,128,0>\"");
179  return;
180  }
181  });
182  options.Add("bounding-size=", delegate(string v)
183  {
184  try
185  {
186  boundingSize = v == null ? new Vector3(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY, float.MaxValue) : Vector3.Parse(v);
187  }
188  catch
189  {
190  m_log.ErrorFormat("[ARCHIVER MODULE] failure parsing bounding cube size");
191  m_log.ErrorFormat("[ARCHIVER MODULE] Must be represented as a positive vector3: --bounding-size \"<256,256,4096>\"");
192  return;
193  }
194  });
195  options.Add("d|debug", delegate(string v) { debug = (v != null); });
196 
197  // Send a message to the region ready module
198  /* bluewall* Disable this for the time being
199  IRegionReadyModule rready = m_scene.RequestModuleInterface<IRegionReadyModule>();
200 
201  if (rready != null)
202  {
203  rready.OarLoadingAlert("load");
204  }
205  */
206 
207  List<string> mainParams = options.Parse(cmdparams);
208 
209 // m_log.DebugFormat("MERGE OAR IS [{0}]", mergeOar);
210 //
211 // foreach (string param in mainParams)
212 // m_log.DebugFormat("GOT PARAM [{0}]", param);
213 
214  Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
215  if (mergeOar) archiveOptions.Add("merge", null);
216  if (skipAssets) archiveOptions.Add("skipAssets", null);
217  if (forceTerrain) archiveOptions.Add("force-terrain", null);
218  if (forceParcels) archiveOptions.Add("force-parcels", null);
219  if (noObjects) archiveOptions.Add("no-objects", null);
220  if (defaultUser != "")
221  {
222  UUID defaultUserUUID = UUID.Zero;
223  try
224  {
225  defaultUserUUID = Scene.UserManagementModule.GetUserIdByName(defaultUser);
226  }
227  catch
228  {
229  m_log.ErrorFormat("[ARCHIVER MODULE] default user must be in format \"First Last\"", defaultUser);
230  }
231  if (defaultUserUUID == UUID.Zero)
232  {
233  m_log.ErrorFormat("[ARCHIVER MODULE] cannot find specified default user {0}", defaultUser);
234  return;
235  }
236  else
237  {
238  archiveOptions.Add("default-user", defaultUserUUID);
239  }
240  }
241  archiveOptions.Add("displacement", displacement);
242  archiveOptions.Add("rotation", rotation);
243  archiveOptions.Add("rotation-center", rotationCenter);
244  archiveOptions.Add("bounding-origin", boundingOrigin);
245  archiveOptions.Add("bounding-size", boundingSize);
246  if (debug) archiveOptions.Add("debug", null);
247 
248  if (mainParams.Count > 2)
249  {
250  DearchiveRegion(mainParams[2], Guid.Empty, archiveOptions);
251  }
252  else
253  {
254  DearchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, Guid.Empty, archiveOptions);
255  }
256  }
257 
262  public void HandleSaveOarConsoleCommand(string module, string[] cmdparams)
263  {
264  Dictionary<string, object> options = new Dictionary<string, object>();
265 
266  OptionSet ops = new OptionSet();
267 
268  // legacy argument [obsolete]
269  ops.Add("p|profile=", delegate(string v) { Console.WriteLine("\n WARNING: -profile option is obsolete and it will not work. Use -home instead.\n"); });
270  // preferred
271  ops.Add("h|home=", delegate(string v) { options["home"] = v; });
272 
273  ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; });
274  ops.Add("publish", v => options["wipe-owners"] = v != null);
275  ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; });
276  ops.Add("all", delegate(string v) { options["all"] = v != null; });
277 
278  List<string> mainParams = ops.Parse(cmdparams);
279 
280  string path;
281  if (mainParams.Count > 2)
282  path = mainParams[2];
283  else
284  path = DEFAULT_OAR_BACKUP_FILENAME;
285 
286  // Not doing this right now as this causes some problems with auto-backup systems. Maybe a force flag is
287  // needed
288 // if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, path))
289 // return;
290 
291  ArchiveRegion(path, options);
292  }
293 
294  public void ArchiveRegion(string savePath, Dictionary<string, object> options)
295  {
296  ArchiveRegion(savePath, Guid.Empty, options);
297  }
298 
299  public void ArchiveRegion(string savePath, Guid requestId, Dictionary<string, object> options)
300  {
301  m_log.InfoFormat(
302  "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath);
303 
304  new ArchiveWriteRequest(Scene, savePath, requestId).ArchiveRegion(options);
305  }
306 
307  public void ArchiveRegion(Stream saveStream)
308  {
309  ArchiveRegion(saveStream, Guid.Empty);
310  }
311 
312  public void ArchiveRegion(Stream saveStream, Guid requestId)
313  {
314  ArchiveRegion(saveStream, requestId, new Dictionary<string, object>());
315  }
316 
317  public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options)
318  {
319  new ArchiveWriteRequest(Scene, saveStream, requestId).ArchiveRegion(options);
320  }
321 
322  public void DearchiveRegion(string loadPath)
323  {
324  Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
325  DearchiveRegion(loadPath, Guid.Empty, archiveOptions);
326  }
327 
328  public void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string, object> options)
329  {
330  m_log.InfoFormat(
331  "[ARCHIVER]: Loading archive to region {0} from {1}", Scene.RegionInfo.RegionName, loadPath);
332 
333  new ArchiveReadRequest(Scene, loadPath, requestId, options).DearchiveRegion();
334  }
335 
336  public void DearchiveRegion(Stream loadStream)
337  {
338  Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
339  DearchiveRegion(loadStream, Guid.Empty, archiveOptions);
340  }
341  public void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary<string, object> options)
342  {
343  new ArchiveReadRequest(Scene, loadStream, requestId, options).DearchiveRegion();
344  }
345  }
346 }
void Initialise(IConfigSource source)
This is called to initialize the region module. For shared modules, this is called exactly once...
void HandleLoadOarConsoleCommand(string module, string[] cmdparams)
Load a whole region from an opensimulator archive.
uint RegionSizeX
X dimension of the region.
Definition: RegionInfo.cs:161
void DearchiveRegion(string loadPath, Guid requestId, Dictionary< string, object > options)
Dearchive the given region archive. This replaces the existing scene.
uint RegionSizeY
X dimension of the region.
Definition: RegionInfo.cs:169
void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary< string, object > options)
Archive the region to a stream.
void ArchiveRegion(Stream saveStream, Guid requestId)
Archive the region to a stream.
void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
void DearchiveRegion(Stream loadStream)
Dearchive a region from a stream. This replaces the existing scene.
void HandleSaveOarConsoleCommand(string module, string[] cmdparams)
Save a region to a file, including all the assets needed to restore it.
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion rotation
Definition: ICM_Api.cs:32
void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary< string, object > options)
Dearchive a region from a stream. This replaces the existing scene.
void ArchiveRegion(string savePath, Dictionary< string, object > options)
Archive the region to the given path
void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
void DearchiveRegion(string loadPath)
Dearchive the given region archive. This replaces the existing scene.
This module loads and saves OpenSimulator region archives
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
void ArchiveRegion(string savePath, Guid requestId, Dictionary< string, object > options)
Archive the region to the given path