diff options
Diffstat (limited to 'OpenSim/Region')
17 files changed, 495 insertions, 107 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 39004d4..8add2af 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs | |||
@@ -267,12 +267,13 @@ namespace OpenSim | |||
267 | 267 | ||
268 | m_console.Commands.AddCommand("region", false, "save oar", | 268 | m_console.Commands.AddCommand("region", false, "save oar", |
269 | //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]", | 269 | //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]", |
270 | "save oar [-p|--profile=<url>] [<OAR path>]", | 270 | "save oar [-p|--profile=<url>] [--noassets] [<OAR path>]", |
271 | "Save a region's data to an OAR archive.", | 271 | "Save a region's data to an OAR archive.", |
272 | // "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine | 272 | // "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine |
273 | "-p|--profile=<url> adds the url of the profile service to the saved user information" + Environment.NewLine | 273 | "-p|--profile=<url> adds the url of the profile service to the saved user information." + Environment.NewLine |
274 | + "The OAR path must be a filesystem path." | 274 | + " The OAR path must be a filesystem path." |
275 | + " If this is not given then the oar is saved to region.oar in the current directory.", | 275 | + " If this is not given then the oar is saved to region.oar in the current directory." + Environment.NewLine |
276 | + "--noassets stops assets being saved to the OAR.", | ||
276 | SaveOar); | 277 | SaveOar); |
277 | 278 | ||
278 | m_console.Commands.AddCommand("region", false, "edit scale", | 279 | m_console.Commands.AddCommand("region", false, "edit scale", |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index c039b5a..b5272ad 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs | |||
@@ -46,6 +46,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
46 | { | 46 | { |
47 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 47 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
48 | 48 | ||
49 | /// <summary> | ||
50 | /// Determine whether this archive will save assets. Default is true. | ||
51 | /// </summary> | ||
52 | public bool SaveAssets { get; set; } | ||
53 | |||
49 | /// <value> | 54 | /// <value> |
50 | /// Used to select all inventory nodes in a folder but not the folder itself | 55 | /// Used to select all inventory nodes in a folder but not the folder itself |
51 | /// </value> | 56 | /// </value> |
@@ -112,6 +117,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
112 | m_invPath = invPath; | 117 | m_invPath = invPath; |
113 | m_saveStream = saveStream; | 118 | m_saveStream = saveStream; |
114 | m_assetGatherer = new UuidGatherer(m_scene.AssetService); | 119 | m_assetGatherer = new UuidGatherer(m_scene.AssetService); |
120 | |||
121 | SaveAssets = true; | ||
115 | } | 122 | } |
116 | 123 | ||
117 | protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids) | 124 | protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids) |
@@ -150,7 +157,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
150 | string serialization = UserInventoryItemSerializer.Serialize(inventoryItem, options, userAccountService); | 157 | string serialization = UserInventoryItemSerializer.Serialize(inventoryItem, options, userAccountService); |
151 | m_archiveWriter.WriteFile(filename, serialization); | 158 | m_archiveWriter.WriteFile(filename, serialization); |
152 | 159 | ||
153 | m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); | 160 | if (SaveAssets) |
161 | m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); | ||
154 | } | 162 | } |
155 | 163 | ||
156 | /// <summary> | 164 | /// <summary> |
@@ -195,6 +203,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
195 | /// </summary> | 203 | /// </summary> |
196 | public void Execute(Dictionary<string, object> options, IUserAccountService userAccountService) | 204 | public void Execute(Dictionary<string, object> options, IUserAccountService userAccountService) |
197 | { | 205 | { |
206 | if (options.ContainsKey("noassets") && (bool)options["noassets"]) | ||
207 | SaveAssets = false; | ||
208 | |||
198 | try | 209 | try |
199 | { | 210 | { |
200 | InventoryFolderBase inventoryFolder = null; | 211 | InventoryFolderBase inventoryFolder = null; |
@@ -285,12 +296,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
285 | 296 | ||
286 | // Don't put all this profile information into the archive right now. | 297 | // Don't put all this profile information into the archive right now. |
287 | //SaveUsers(); | 298 | //SaveUsers(); |
288 | 299 | ||
289 | new AssetsRequest( | 300 | if (SaveAssets) |
290 | new AssetsArchiver(m_archiveWriter), | 301 | { |
291 | m_assetUuids, m_scene.AssetService, | 302 | m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); |
292 | m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, | 303 | |
293 | options, ReceivedAllAssets).Execute(); | 304 | new AssetsRequest( |
305 | new AssetsArchiver(m_archiveWriter), | ||
306 | m_assetUuids, m_scene.AssetService, | ||
307 | m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, | ||
308 | options, ReceivedAllAssets).Execute(); | ||
309 | } | ||
310 | else | ||
311 | { | ||
312 | m_log.DebugFormat("[INVENTORY ARCHIVER]: Not saving assets since --noassets was specified"); | ||
313 | |||
314 | ReceivedAllAssets(new List<UUID>(), new List<UUID>()); | ||
315 | } | ||
294 | } | 316 | } |
295 | catch (Exception) | 317 | catch (Exception) |
296 | { | 318 | { |
@@ -387,19 +409,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
387 | /// </summary> | 409 | /// </summary> |
388 | /// <param name="options"></param> | 410 | /// <param name="options"></param> |
389 | /// <returns></returns> | 411 | /// <returns></returns> |
390 | public static string CreateControlFile(Dictionary<string, object> options) | 412 | public string CreateControlFile(Dictionary<string, object> options) |
391 | { | 413 | { |
392 | int majorVersion, minorVersion; | 414 | int majorVersion, minorVersion; |
393 | 415 | ||
394 | if (options.ContainsKey("profile")) | 416 | if (options.ContainsKey("profile")) |
395 | { | 417 | { |
396 | majorVersion = 1; | 418 | majorVersion = 1; |
397 | minorVersion = 1; | 419 | minorVersion = 2; |
398 | } | 420 | } |
399 | else | 421 | else |
400 | { | 422 | { |
401 | majorVersion = 0; | 423 | majorVersion = 0; |
402 | minorVersion = 2; | 424 | minorVersion = 3; |
403 | } | 425 | } |
404 | 426 | ||
405 | m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion); | 427 | m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion); |
@@ -411,6 +433,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
411 | xtw.WriteStartElement("archive"); | 433 | xtw.WriteStartElement("archive"); |
412 | xtw.WriteAttributeString("major_version", majorVersion.ToString()); | 434 | xtw.WriteAttributeString("major_version", majorVersion.ToString()); |
413 | xtw.WriteAttributeString("minor_version", minorVersion.ToString()); | 435 | xtw.WriteAttributeString("minor_version", minorVersion.ToString()); |
436 | |||
437 | xtw.WriteElementString("assets_included", SaveAssets.ToString()); | ||
438 | |||
414 | xtw.WriteEndElement(); | 439 | xtw.WriteEndElement(); |
415 | 440 | ||
416 | xtw.Flush(); | 441 | xtw.Flush(); |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index 576a154..e0b02aa 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs | |||
@@ -122,7 +122,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
122 | 122 | ||
123 | scene.AddCommand( | 123 | scene.AddCommand( |
124 | this, "save iar", | 124 | this, "save iar", |
125 | "save iar [--p|-profile=<url>] <first> <last> <inventory path> <password> [<IAR path>] [--v|-verbose]", | 125 | "save iar [--p|-profile=<url>] [--noassets] <first> <last> <inventory path> <password> [<IAR path>] [--v|-verbose]", |
126 | "Save user inventory archive (IAR).", | 126 | "Save user inventory archive (IAR).", |
127 | "<first> is the user's first name." + Environment.NewLine | 127 | "<first> is the user's first name." + Environment.NewLine |
128 | + "<last> is the user's last name." + Environment.NewLine | 128 | + "<last> is the user's last name." + Environment.NewLine |
@@ -130,6 +130,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
130 | + "-p|--profile=<url> adds the url of the profile service to the saved user information." + Environment.NewLine | 130 | + "-p|--profile=<url> adds the url of the profile service to the saved user information." + Environment.NewLine |
131 | + "-c|--creators preserves information about foreign creators." + Environment.NewLine | 131 | + "-c|--creators preserves information about foreign creators." + Environment.NewLine |
132 | + "-v|--verbose extra debug messages." + Environment.NewLine | 132 | + "-v|--verbose extra debug messages." + Environment.NewLine |
133 | + "--noassets stops assets being saved to the IAR." | ||
133 | + "<IAR path> is the filesystem path at which to save the IAR." | 134 | + "<IAR path> is the filesystem path at which to save the IAR." |
134 | + string.Format(" If this is not given then the filename {0} in the current directory is used", DEFAULT_INV_BACKUP_FILENAME), | 135 | + string.Format(" If this is not given then the filename {0} in the current directory is used", DEFAULT_INV_BACKUP_FILENAME), |
135 | HandleSaveInvConsoleCommand); | 136 | HandleSaveInvConsoleCommand); |
@@ -398,6 +399,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
398 | ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); | 399 | ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); |
399 | ops.Add("v|verbose", delegate(string v) { options["verbose"] = v; }); | 400 | ops.Add("v|verbose", delegate(string v) { options["verbose"] = v; }); |
400 | ops.Add("c|creators", delegate(string v) { options["creators"] = v; }); | 401 | ops.Add("c|creators", delegate(string v) { options["creators"] = v; }); |
402 | ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); | ||
401 | 403 | ||
402 | List<string> mainParams = ops.Parse(cmdparams); | 404 | List<string> mainParams = ops.Parse(cmdparams); |
403 | 405 | ||
@@ -406,7 +408,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
406 | if (mainParams.Count < 6) | 408 | if (mainParams.Count < 6) |
407 | { | 409 | { |
408 | m_log.Error( | 410 | m_log.Error( |
409 | "[INVENTORY ARCHIVER]: usage is save iar [--p|-profile=<url>] <first name> <last name> <inventory path> <user password> [<save file path>]"); | 411 | "[INVENTORY ARCHIVER]: usage is save iar [--p|-profile=<url>] [--noassets] <first name> <last name> <inventory path> <user password> [<save file path>]"); |
410 | return; | 412 | return; |
411 | } | 413 | } |
412 | 414 | ||
@@ -423,16 +425,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
423 | m_log.InfoFormat( | 425 | m_log.InfoFormat( |
424 | "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", | 426 | "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", |
425 | savePath, invPath, firstName, lastName); | 427 | savePath, invPath, firstName, lastName); |
426 | 428 | ||
429 | lock (m_pendingConsoleSaves) | ||
430 | m_pendingConsoleSaves.Add(id); | ||
431 | |||
427 | ArchiveInventory(id, firstName, lastName, invPath, pass, savePath, options); | 432 | ArchiveInventory(id, firstName, lastName, invPath, pass, savePath, options); |
428 | } | 433 | } |
429 | catch (InventoryArchiverException e) | 434 | catch (InventoryArchiverException e) |
430 | { | 435 | { |
431 | m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); | 436 | m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); |
432 | } | 437 | } |
433 | |||
434 | lock (m_pendingConsoleSaves) | ||
435 | m_pendingConsoleSaves.Add(id); | ||
436 | } | 438 | } |
437 | 439 | ||
438 | private void SaveInvConsoleCommandCompleted( | 440 | private void SaveInvConsoleCommandCompleted( |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index d97311a..ae3ab21 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs | |||
@@ -123,11 +123,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
123 | } | 123 | } |
124 | 124 | ||
125 | /// <summary> | 125 | /// <summary> |
126 | /// Test saving a single inventory item to a V0.1 OpenSim Inventory Archive | 126 | /// Test saving a single inventory item to an IAR |
127 | /// (subject to change since there is no fixed format yet). | 127 | /// (subject to change since there is no fixed format yet). |
128 | /// </summary> | 128 | /// </summary> |
129 | [Test] | 129 | [Test] |
130 | public void TestSaveItemToIarV0_1() | 130 | public void TestSaveItemToIar() |
131 | { | 131 | { |
132 | TestHelper.InMethod(); | 132 | TestHelper.InMethod(); |
133 | // log4net.Config.XmlConfigurator.Configure(); | 133 | // log4net.Config.XmlConfigurator.Configure(); |
@@ -217,6 +217,106 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
217 | 217 | ||
218 | // TODO: Test presence of more files and contents of files. | 218 | // TODO: Test presence of more files and contents of files. |
219 | } | 219 | } |
220 | |||
221 | /// <summary> | ||
222 | /// Test saving a single inventory item to an IAR without its asset | ||
223 | /// </summary> | ||
224 | [Test] | ||
225 | public void TestSaveItemToIarNoAssets() | ||
226 | { | ||
227 | TestHelper.InMethod(); | ||
228 | // log4net.Config.XmlConfigurator.Configure(); | ||
229 | |||
230 | // Create user | ||
231 | string userFirstName = "Jock"; | ||
232 | string userLastName = "Stirrup"; | ||
233 | string userPassword = "troll"; | ||
234 | UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); | ||
235 | UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); | ||
236 | |||
237 | // Create asset | ||
238 | UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); | ||
239 | SceneObjectGroup object1 = SceneSetupHelpers.CreateSceneObject(1, ownerId, "My Little Dog Object", 0x50); | ||
240 | |||
241 | UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); | ||
242 | AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); | ||
243 | m_scene.AssetService.Store(asset1); | ||
244 | |||
245 | // Create item | ||
246 | UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); | ||
247 | string item1Name = "My Little Dog"; | ||
248 | InventoryItemBase item1 = new InventoryItemBase(); | ||
249 | item1.Name = item1Name; | ||
250 | item1.AssetID = asset1.FullID; | ||
251 | item1.ID = item1Id; | ||
252 | InventoryFolderBase objsFolder | ||
253 | = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, userId, "Objects")[0]; | ||
254 | item1.Folder = objsFolder.ID; | ||
255 | m_scene.AddInventoryItem(item1); | ||
256 | |||
257 | MemoryStream archiveWriteStream = new MemoryStream(); | ||
258 | |||
259 | Dictionary<string, Object> options = new Dictionary<string, Object>(); | ||
260 | options.Add("noassets", true); | ||
261 | |||
262 | // When we're not saving assets, archiving is being done synchronously. | ||
263 | m_archiverModule.ArchiveInventory( | ||
264 | Guid.NewGuid(), userFirstName, userLastName, "Objects/" + item1Name, userPassword, archiveWriteStream, options); | ||
265 | |||
266 | byte[] archive = archiveWriteStream.ToArray(); | ||
267 | MemoryStream archiveReadStream = new MemoryStream(archive); | ||
268 | TarArchiveReader tar = new TarArchiveReader(archiveReadStream); | ||
269 | |||
270 | //bool gotControlFile = false; | ||
271 | bool gotObject1File = false; | ||
272 | //bool gotObject2File = false; | ||
273 | string expectedObject1FileName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1); | ||
274 | string expectedObject1FilePath = string.Format( | ||
275 | "{0}{1}", | ||
276 | ArchiveConstants.INVENTORY_PATH, | ||
277 | expectedObject1FileName); | ||
278 | |||
279 | string filePath; | ||
280 | TarArchiveReader.TarEntryType tarEntryType; | ||
281 | |||
282 | // Console.WriteLine("Reading archive"); | ||
283 | |||
284 | while (tar.ReadEntry(out filePath, out tarEntryType) != null) | ||
285 | { | ||
286 | Console.WriteLine("Got {0}", filePath); | ||
287 | |||
288 | // if (ArchiveConstants.CONTROL_FILE_PATH == filePath) | ||
289 | // { | ||
290 | // gotControlFile = true; | ||
291 | // } | ||
292 | |||
293 | if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml")) | ||
294 | { | ||
295 | // string fileName = filePath.Remove(0, "Objects/".Length); | ||
296 | // | ||
297 | // if (fileName.StartsWith(part1.Name)) | ||
298 | // { | ||
299 | Assert.That(expectedObject1FilePath, Is.EqualTo(filePath)); | ||
300 | gotObject1File = true; | ||
301 | // } | ||
302 | // else if (fileName.StartsWith(part2.Name)) | ||
303 | // { | ||
304 | // Assert.That(fileName, Is.EqualTo(expectedObject2FileName)); | ||
305 | // gotObject2File = true; | ||
306 | // } | ||
307 | } | ||
308 | else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) | ||
309 | { | ||
310 | Assert.Fail("Found asset path in TestSaveItemToIarNoAssets()"); | ||
311 | } | ||
312 | } | ||
313 | |||
314 | // Assert.That(gotControlFile, Is.True, "No control file in archive"); | ||
315 | Assert.That(gotObject1File, Is.True, "No item1 file in archive"); | ||
316 | // Assert.That(gotObject2File, Is.True, "No object2 file in archive"); | ||
317 | |||
318 | // TODO: Test presence of more files and contents of files. | ||
319 | } | ||
220 | 320 | ||
221 | /// <summary> | 321 | /// <summary> |
222 | /// Test case where a creator account exists for the creator UUID embedded in item metadata and serialized | 322 | /// Test case where a creator account exists for the creator UUID embedded in item metadata and serialized |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index 597b780..10a83ee 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs | |||
@@ -49,7 +49,7 @@ 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> | 53 | /// <summary> |
54 | /// The minimum major version of OAR that we can write. | 54 | /// The minimum major version of OAR that we can write. |
55 | /// </summary> | 55 | /// </summary> |
@@ -58,7 +58,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
58 | /// <summary> | 58 | /// <summary> |
59 | /// The maximum major version of OAR that we can write. | 59 | /// The maximum major version of OAR that we can write. |
60 | /// </summary> | 60 | /// </summary> |
61 | public static int MAX_MAJOR_VERSION = 0; | 61 | public static int MAX_MAJOR_VERSION = 0; |
62 | |||
63 | /// <summary> | ||
64 | /// Determine whether this archive will save assets. Default is true. | ||
65 | /// </summary> | ||
66 | public bool SaveAssets { get; set; } | ||
62 | 67 | ||
63 | protected Scene m_scene; | 68 | protected Scene m_scene; |
64 | protected Stream m_saveStream; | 69 | protected Stream m_saveStream; |
@@ -73,10 +78,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
73 | /// <exception cref="System.IO.IOException"> | 78 | /// <exception cref="System.IO.IOException"> |
74 | /// If there was a problem opening a stream for the file specified by the savePath | 79 | /// If there was a problem opening a stream for the file specified by the savePath |
75 | /// </exception> | 80 | /// </exception> |
76 | public ArchiveWriteRequestPreparation(Scene scene, string savePath, Guid requestId) | 81 | public ArchiveWriteRequestPreparation(Scene scene, string savePath, Guid requestId) : this(scene, requestId) |
77 | { | 82 | { |
78 | m_scene = scene; | ||
79 | |||
80 | try | 83 | try |
81 | { | 84 | { |
82 | m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress); | 85 | m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress); |
@@ -86,10 +89,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
86 | m_log.ErrorFormat( | 89 | m_log.ErrorFormat( |
87 | "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." | 90 | "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." |
88 | + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); | 91 | + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); |
89 | m_log.Error(e); | 92 | m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace); |
90 | } | 93 | } |
91 | |||
92 | m_requestId = requestId; | ||
93 | } | 94 | } |
94 | 95 | ||
95 | /// <summary> | 96 | /// <summary> |
@@ -98,11 +99,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
98 | /// <param name="scene"></param> | 99 | /// <param name="scene"></param> |
99 | /// <param name="saveStream">The stream to which to save data.</param> | 100 | /// <param name="saveStream">The stream to which to save data.</param> |
100 | /// <param name="requestId">The id associated with this request</param> | 101 | /// <param name="requestId">The id associated with this request</param> |
101 | public ArchiveWriteRequestPreparation(Scene scene, Stream saveStream, Guid requestId) | 102 | public ArchiveWriteRequestPreparation(Scene scene, Stream saveStream, Guid requestId) : this(scene, requestId) |
102 | { | 103 | { |
103 | m_scene = scene; | ||
104 | m_saveStream = saveStream; | 104 | m_saveStream = saveStream; |
105 | } | ||
106 | |||
107 | protected ArchiveWriteRequestPreparation(Scene scene, Guid requestId) | ||
108 | { | ||
109 | m_scene = scene; | ||
105 | m_requestId = requestId; | 110 | m_requestId = requestId; |
111 | |||
112 | SaveAssets = true; | ||
106 | } | 113 | } |
107 | 114 | ||
108 | /// <summary> | 115 | /// <summary> |
@@ -111,22 +118,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
111 | /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception> | 118 | /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception> |
112 | public void ArchiveRegion(Dictionary<string, object> options) | 119 | public void ArchiveRegion(Dictionary<string, object> options) |
113 | { | 120 | { |
121 | if (options.ContainsKey("noassets") && (bool)options["noassets"]) | ||
122 | SaveAssets = false; | ||
123 | |||
114 | try | 124 | try |
115 | { | 125 | { |
116 | Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>(); | 126 | Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>(); |
117 | 127 | ||
118 | EntityBase[] entities = m_scene.GetEntities(); | 128 | EntityBase[] entities = m_scene.GetEntities(); |
119 | List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); | 129 | List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); |
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 | 130 | ||
131 | // Filter entities so that we only have scene objects. | 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 | 132 | // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods |
@@ -141,17 +141,24 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
141 | sceneObjects.Add((SceneObjectGroup)entity); | 141 | sceneObjects.Add((SceneObjectGroup)entity); |
142 | } | 142 | } |
143 | } | 143 | } |
144 | 144 | ||
145 | UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); | 145 | if (SaveAssets) |
146 | 146 | { | |
147 | foreach (SceneObjectGroup sceneObject in sceneObjects) | 147 | UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); |
148 | |||
149 | foreach (SceneObjectGroup sceneObject in sceneObjects) | ||
150 | { | ||
151 | assetGatherer.GatherAssetUuids(sceneObject, assetUuids); | ||
152 | } | ||
153 | |||
154 | m_log.DebugFormat( | ||
155 | "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", | ||
156 | sceneObjects.Count, assetUuids.Count); | ||
157 | } | ||
158 | else | ||
148 | { | 159 | { |
149 | assetGatherer.GatherAssetUuids(sceneObject, assetUuids); | 160 | m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); |
150 | } | 161 | } |
151 | |||
152 | m_log.DebugFormat( | ||
153 | "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", | ||
154 | sceneObjects.Count, assetUuids.Count); | ||
155 | 162 | ||
156 | // Make sure that we also request terrain texture assets | 163 | // Make sure that we also request terrain texture assets |
157 | RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; | 164 | RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; |
@@ -187,11 +194,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
187 | // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this | 194 | // 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)); | 195 | archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options)); |
189 | m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); | 196 | m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); |
190 | 197 | ||
191 | new AssetsRequest( | 198 | if (SaveAssets) |
192 | new AssetsArchiver(archiveWriter), assetUuids, | 199 | new AssetsRequest( |
193 | m_scene.AssetService, m_scene.UserAccountService, | 200 | new AssetsArchiver(archiveWriter), assetUuids, |
194 | m_scene.RegionInfo.ScopeID, options, awre.ReceivedAllAssets).Execute(); | 201 | m_scene.AssetService, m_scene.UserAccountService, |
202 | m_scene.RegionInfo.ScopeID, options, awre.ReceivedAllAssets).Execute(); | ||
203 | else | ||
204 | awre.ReceivedAllAssets(new List<UUID>(), new List<UUID>()); | ||
195 | } | 205 | } |
196 | catch (Exception) | 206 | catch (Exception) |
197 | { | 207 | { |
@@ -204,9 +214,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
204 | /// Create the control file for the most up to date archive | 214 | /// Create the control file for the most up to date archive |
205 | /// </summary> | 215 | /// </summary> |
206 | /// <returns></returns> | 216 | /// <returns></returns> |
207 | public static string CreateControlFile(Dictionary<string, object> options) | 217 | public string CreateControlFile(Dictionary<string, object> options) |
208 | { | 218 | { |
209 | int majorVersion = MAX_MAJOR_VERSION, minorVersion = 6; | 219 | int majorVersion = MAX_MAJOR_VERSION, minorVersion = 7; |
210 | // | 220 | // |
211 | // if (options.ContainsKey("version")) | 221 | // if (options.ContainsKey("version")) |
212 | // { | 222 | // { |
@@ -258,6 +268,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
258 | xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString()); | 268 | xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString()); |
259 | xtw.WriteElementString("id", UUID.Random().ToString()); | 269 | xtw.WriteElementString("id", UUID.Random().ToString()); |
260 | xtw.WriteEndElement(); | 270 | xtw.WriteEndElement(); |
271 | |||
272 | xtw.WriteElementString("assets_included", SaveAssets.ToString()); | ||
273 | |||
261 | xtw.WriteEndElement(); | 274 | xtw.WriteEndElement(); |
262 | 275 | ||
263 | xtw.Flush(); | 276 | xtw.Flush(); |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index 9277c59..08eb80c 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs | |||
@@ -127,6 +127,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
127 | OptionSet ops = new OptionSet(); | 127 | OptionSet ops = new OptionSet(); |
128 | // ops.Add("v|version=", delegate(string v) { options["version"] = v; }); | 128 | // ops.Add("v|version=", delegate(string v) { options["version"] = v; }); |
129 | ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); | 129 | ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); |
130 | ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); | ||
130 | 131 | ||
131 | List<string> mainParams = ops.Parse(cmdparams); | 132 | List<string> mainParams = ops.Parse(cmdparams); |
132 | 133 | ||
@@ -160,7 +161,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
160 | 161 | ||
161 | public void ArchiveRegion(Stream saveStream, Guid requestId) | 162 | public void ArchiveRegion(Stream saveStream, Guid requestId) |
162 | { | 163 | { |
163 | new ArchiveWriteRequestPreparation(m_scene, saveStream, requestId).ArchiveRegion(new Dictionary<string, object>()); | 164 | ArchiveRegion(saveStream, requestId, new Dictionary<string, object>()); |
165 | } | ||
166 | |||
167 | public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options) | ||
168 | { | ||
169 | new ArchiveWriteRequestPreparation(m_scene, saveStream, requestId).ArchiveRegion(options); | ||
164 | } | 170 | } |
165 | 171 | ||
166 | public void DearchiveRegion(string loadPath) | 172 | public void DearchiveRegion(string loadPath) |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 2eb2861..34e2e23 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs | |||
@@ -212,6 +212,89 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
212 | } | 212 | } |
213 | 213 | ||
214 | /// <summary> | 214 | /// <summary> |
215 | /// Test saving an OpenSim Region Archive with the no assets option | ||
216 | /// </summary> | ||
217 | [Test] | ||
218 | public void TestSaveOarNoAssets() | ||
219 | { | ||
220 | TestHelper.InMethod(); | ||
221 | // log4net.Config.XmlConfigurator.Configure(); | ||
222 | |||
223 | SceneObjectPart part1 = CreateSceneObjectPart1(); | ||
224 | SceneObjectGroup sog1 = new SceneObjectGroup(part1); | ||
225 | m_scene.AddNewSceneObject(sog1, false); | ||
226 | |||
227 | SceneObjectPart part2 = CreateSceneObjectPart2(); | ||
228 | |||
229 | AssetNotecard nc = new AssetNotecard(); | ||
230 | nc.BodyText = "Hello World!"; | ||
231 | nc.Encode(); | ||
232 | UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); | ||
233 | UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); | ||
234 | AssetBase ncAsset | ||
235 | = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); | ||
236 | m_scene.AssetService.Store(ncAsset); | ||
237 | SceneObjectGroup sog2 = new SceneObjectGroup(part2); | ||
238 | TaskInventoryItem ncItem | ||
239 | = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; | ||
240 | part2.Inventory.AddInventoryItem(ncItem, true); | ||
241 | |||
242 | m_scene.AddNewSceneObject(sog2, false); | ||
243 | |||
244 | MemoryStream archiveWriteStream = new MemoryStream(); | ||
245 | |||
246 | Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); | ||
247 | |||
248 | Dictionary<string, Object> options = new Dictionary<string, Object>(); | ||
249 | options.Add("noassets", true); | ||
250 | m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options); | ||
251 | //AssetServerBase assetServer = (AssetServerBase)scene.CommsManager.AssetCache.AssetServer; | ||
252 | //while (assetServer.HasWaitingRequests()) | ||
253 | // assetServer.ProcessNextRequest(); | ||
254 | |||
255 | // Don't wait for completion - with --noassets save oar happens synchronously | ||
256 | // Monitor.Wait(this, 60000); | ||
257 | |||
258 | Assert.That(m_lastRequestId, Is.EqualTo(requestId)); | ||
259 | |||
260 | byte[] archive = archiveWriteStream.ToArray(); | ||
261 | MemoryStream archiveReadStream = new MemoryStream(archive); | ||
262 | TarArchiveReader tar = new TarArchiveReader(archiveReadStream); | ||
263 | |||
264 | List<string> foundPaths = new List<string>(); | ||
265 | List<string> expectedPaths = new List<string>(); | ||
266 | expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog1)); | ||
267 | expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2)); | ||
268 | |||
269 | string filePath; | ||
270 | TarArchiveReader.TarEntryType tarEntryType; | ||
271 | |||
272 | byte[] data = tar.ReadEntry(out filePath, out tarEntryType); | ||
273 | Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); | ||
274 | |||
275 | ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); | ||
276 | arr.LoadControlFile(filePath, data); | ||
277 | |||
278 | Assert.That(arr.ControlFileLoaded, Is.True); | ||
279 | |||
280 | while (tar.ReadEntry(out filePath, out tarEntryType) != null) | ||
281 | { | ||
282 | if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) | ||
283 | { | ||
284 | Assert.Fail("Asset was found in saved oar of TestSaveOarNoAssets()"); | ||
285 | } | ||
286 | else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) | ||
287 | { | ||
288 | foundPaths.Add(filePath); | ||
289 | } | ||
290 | } | ||
291 | |||
292 | Assert.That(foundPaths, Is.EquivalentTo(expectedPaths)); | ||
293 | |||
294 | // TODO: Test presence of more files and contents of files. | ||
295 | } | ||
296 | |||
297 | /// <summary> | ||
215 | /// Test loading an OpenSim Region Archive. | 298 | /// Test loading an OpenSim Region Archive. |
216 | /// </summary> | 299 | /// </summary> |
217 | [Test] | 300 | [Test] |
@@ -230,7 +313,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
230 | // upset load | 313 | // upset load |
231 | tar.WriteDir(ArchiveConstants.TERRAINS_PATH); | 314 | tar.WriteDir(ArchiveConstants.TERRAINS_PATH); |
232 | 315 | ||
233 | tar.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestPreparation.CreateControlFile(new Dictionary<string, Object>())); | 316 | tar.WriteFile( |
317 | ArchiveConstants.CONTROL_FILE_PATH, | ||
318 | new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>())); | ||
234 | 319 | ||
235 | SceneObjectPart part1 = CreateSceneObjectPart1(); | 320 | SceneObjectPart part1 = CreateSceneObjectPart1(); |
236 | SceneObjectGroup object1 = new SceneObjectGroup(part1); | 321 | SceneObjectGroup object1 = new SceneObjectGroup(part1); |
@@ -331,7 +416,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
331 | TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); | 416 | TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); |
332 | 417 | ||
333 | tar.WriteDir(ArchiveConstants.TERRAINS_PATH); | 418 | tar.WriteDir(ArchiveConstants.TERRAINS_PATH); |
334 | tar.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestPreparation.CreateControlFile(new Dictionary<string, Object>())); | 419 | tar.WriteFile( |
420 | ArchiveConstants.CONTROL_FILE_PATH, | ||
421 | new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>())); | ||
335 | 422 | ||
336 | RegionSettings rs = new RegionSettings(); | 423 | RegionSettings rs = new RegionSettings(); |
337 | rs.AgentLimit = 17; | 424 | rs.AgentLimit = 17; |
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs index d8229de..3fafc47 100644 --- a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs | |||
@@ -52,31 +52,44 @@ namespace OpenSim.Region.Framework.Interfaces | |||
52 | /// <summary> | 52 | /// <summary> |
53 | /// Archive the region to the given path | 53 | /// Archive the region to the given path |
54 | /// </summary> | 54 | /// </summary> |
55 | /// | 55 | /// <remarks> |
56 | /// This method occurs asynchronously. If you want notification of when it has completed then subscribe to | 56 | /// This method occurs asynchronously. If you want notification of when it has completed then subscribe to |
57 | /// the EventManager.OnOarFileSaved event. | 57 | /// the EventManager.OnOarFileSaved event. |
58 | /// | 58 | /// </remarks> |
59 | /// <param name="savePath"></param> | 59 | /// <param name="savePath"></param> |
60 | /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param> | 60 | /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param> |
61 | /// <param name="options">Options for the save</param> | ||
61 | void ArchiveRegion(string savePath, Guid requestId, Dictionary<string, object> options); | 62 | void ArchiveRegion(string savePath, Guid requestId, Dictionary<string, object> options); |
62 | 63 | ||
63 | /// <summary> | 64 | /// <summary> |
64 | /// Archive the region to a stream. | 65 | /// Archive the region to a stream. |
65 | /// </summary> | 66 | /// </summary> |
66 | /// | 67 | /// <remarks> |
67 | /// This method occurs asynchronously. If you want notification of when it has completed then subscribe to | 68 | /// This method occurs asynchronously. If you want notification of when it has completed then subscribe to |
68 | /// the EventManager.OnOarFileSaved event. | 69 | /// the EventManager.OnOarFileSaved event. |
69 | /// | 70 | /// </remarks> |
70 | /// <param name="saveStream"></param> | 71 | /// <param name="saveStream"></param> |
71 | /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param> | 72 | /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param> |
72 | void ArchiveRegion(Stream saveStream, Guid requestId); | 73 | void ArchiveRegion(Stream saveStream, Guid requestId); |
73 | 74 | ||
74 | /// <summary> | 75 | /// <summary> |
76 | /// Archive the region to a stream. | ||
77 | /// </summary> | ||
78 | /// <remarks> | ||
79 | /// This method occurs asynchronously. If you want notification of when it has completed then subscribe to | ||
80 | /// the EventManager.OnOarFileSaved event. | ||
81 | /// </remarks> | ||
82 | /// <param name="saveStream"></param> | ||
83 | /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param> | ||
84 | /// <param name="options">Options for the save</param> | ||
85 | void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options); | ||
86 | |||
87 | /// <summary> | ||
75 | /// Dearchive the given region archive. This replaces the existing scene. | 88 | /// Dearchive the given region archive. This replaces the existing scene. |
76 | /// </summary> | 89 | /// </summary> |
77 | /// | 90 | /// <remarks> |
78 | /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. | 91 | /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. |
79 | /// | 92 | /// </remarks> |
80 | /// <param name="loadPath"></param> | 93 | /// <param name="loadPath"></param> |
81 | void DearchiveRegion(string loadPath); | 94 | void DearchiveRegion(string loadPath); |
82 | 95 | ||
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs index fecdd1b..d9752e6 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs | |||
@@ -50,5 +50,7 @@ namespace OpenSim.Region.Framework.Interfaces | |||
50 | void ResumeScript(UUID itemID); | 50 | void ResumeScript(UUID itemID); |
51 | 51 | ||
52 | ArrayList GetScriptErrors(UUID itemID); | 52 | ArrayList GetScriptErrors(UUID itemID); |
53 | |||
54 | void SaveAllState(); | ||
53 | } | 55 | } |
54 | } | 56 | } |
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index fd62535..e04317b 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs | |||
@@ -111,6 +111,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
111 | 111 | ||
112 | public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; | 112 | public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; |
113 | 113 | ||
114 | public delegate void SceneShuttingDownDelegate(Scene scene); | ||
115 | |||
116 | public event SceneShuttingDownDelegate OnSceneShuttingDown; | ||
117 | |||
114 | /// <summary> | 118 | /// <summary> |
115 | /// Fired when an object is touched/grabbed. | 119 | /// Fired when an object is touched/grabbed. |
116 | /// </summary> | 120 | /// </summary> |
@@ -2193,5 +2197,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
2193 | } | 2197 | } |
2194 | } | 2198 | } |
2195 | } | 2199 | } |
2200 | |||
2201 | public void TriggerSceneShuttingDown(Scene s) | ||
2202 | { | ||
2203 | SceneShuttingDownDelegate handler = OnSceneShuttingDown; | ||
2204 | if (handler != null) | ||
2205 | { | ||
2206 | foreach (SceneShuttingDownDelegate d in handler.GetInvocationList()) | ||
2207 | { | ||
2208 | try | ||
2209 | { | ||
2210 | d(s); | ||
2211 | } | ||
2212 | catch (Exception e) | ||
2213 | { | ||
2214 | m_log.ErrorFormat( | ||
2215 | "[EVENT MANAGER]: Delegate for TriggerSceneShuttingDown failed - continuing. {0} {1}", | ||
2216 | e.Message, e.StackTrace); | ||
2217 | } | ||
2218 | } | ||
2219 | } | ||
2220 | } | ||
2196 | } | 2221 | } |
2197 | } | 2222 | } |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index b9690fe..4aae13c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -204,6 +204,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
204 | 204 | ||
205 | private Timer m_mapGenerationTimer = new Timer(); | 205 | private Timer m_mapGenerationTimer = new Timer(); |
206 | private bool m_generateMaptiles; | 206 | private bool m_generateMaptiles; |
207 | private bool m_useBackup = true; | ||
207 | 208 | ||
208 | // private Dictionary<UUID, string[]> m_UserNamesCache = new Dictionary<UUID, string[]>(); | 209 | // private Dictionary<UUID, string[]> m_UserNamesCache = new Dictionary<UUID, string[]>(); |
209 | 210 | ||
@@ -459,6 +460,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
459 | get { return m_sceneGraph; } | 460 | get { return m_sceneGraph; } |
460 | } | 461 | } |
461 | 462 | ||
463 | public bool UseBackup | ||
464 | { | ||
465 | get { return m_useBackup; } | ||
466 | } | ||
467 | |||
462 | // an instance to the physics plugin's Scene object. | 468 | // an instance to the physics plugin's Scene object. |
463 | public PhysicsScene PhysicsScene | 469 | public PhysicsScene PhysicsScene |
464 | { | 470 | { |
@@ -647,6 +653,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
647 | IConfig startupConfig = m_config.Configs["Startup"]; | 653 | IConfig startupConfig = m_config.Configs["Startup"]; |
648 | 654 | ||
649 | m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); | 655 | m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); |
656 | m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup); | ||
657 | if (!m_useBackup) | ||
658 | m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); | ||
650 | 659 | ||
651 | //Animation states | 660 | //Animation states |
652 | m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); | 661 | m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); |
@@ -1064,6 +1073,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1064 | shuttingdown = true; | 1073 | shuttingdown = true; |
1065 | 1074 | ||
1066 | m_log.Debug("[SCENE]: Persisting changed objects"); | 1075 | m_log.Debug("[SCENE]: Persisting changed objects"); |
1076 | EventManager.TriggerSceneShuttingDown(this); | ||
1077 | |||
1067 | EntityBase[] entities = GetEntities(); | 1078 | EntityBase[] entities = GetEntities(); |
1068 | foreach (EntityBase entity in entities) | 1079 | foreach (EntityBase entity in entities) |
1069 | { | 1080 | { |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 19a9506..9b9374b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -1335,7 +1335,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1335 | } | 1335 | } |
1336 | } | 1336 | } |
1337 | 1337 | ||
1338 | if (HasGroupChanged) | 1338 | if (m_scene.UseBackup && HasGroupChanged) |
1339 | { | 1339 | { |
1340 | // don't backup while it's selected or you're asking for changes mid stream. | 1340 | // don't backup while it's selected or you're asking for changes mid stream. |
1341 | if (isTimeToPersist() || forcedBackup) | 1341 | if (isTimeToPersist() || forcedBackup) |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 8a8a699..331abb2 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | |||
@@ -144,11 +144,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
144 | 144 | ||
145 | public Vector3 StatusSandboxPos; | 145 | public Vector3 StatusSandboxPos; |
146 | 146 | ||
147 | // TODO: This needs to be persisted in next XML version update! | 147 | [XmlIgnore] |
148 | 148 | public int[] PayPrice = {-2,-2,-2,-2,-2}; | |
149 | public readonly int[] PayPrice = {-2,-2,-2,-2,-2}; | 149 | |
150 | 150 | [XmlIgnore] | |
151 | |||
152 | public PhysicsActor PhysActor | 151 | public PhysicsActor PhysActor |
153 | { | 152 | { |
154 | get { return m_physActor; } | 153 | get { return m_physActor; } |
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index bb8a83a..872816c 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs | |||
@@ -341,6 +341,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
341 | m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl); | 341 | m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl); |
342 | m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation); | 342 | m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation); |
343 | m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem); | 343 | m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem); |
344 | m_SOPXmlProcessors.Add("PayPrice0", ProcessPayPrice0); | ||
345 | m_SOPXmlProcessors.Add("PayPrice1", ProcessPayPrice1); | ||
346 | m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2); | ||
347 | m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); | ||
348 | m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); | ||
344 | #endregion | 349 | #endregion |
345 | 350 | ||
346 | #region TaskInventoryXmlProcessors initialization | 351 | #region TaskInventoryXmlProcessors initialization |
@@ -698,6 +703,32 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
698 | { | 703 | { |
699 | obj.ParticleSystem = Convert.FromBase64String(reader.ReadElementContentAsString("ParticleSystem", String.Empty)); | 704 | obj.ParticleSystem = Convert.FromBase64String(reader.ReadElementContentAsString("ParticleSystem", String.Empty)); |
700 | } | 705 | } |
706 | |||
707 | private static void ProcessPayPrice0(SceneObjectPart obj, XmlTextReader reader) | ||
708 | { | ||
709 | obj.PayPrice[0] = (int)reader.ReadElementContentAsInt("PayPrice0", String.Empty); | ||
710 | } | ||
711 | |||
712 | private static void ProcessPayPrice1(SceneObjectPart obj, XmlTextReader reader) | ||
713 | { | ||
714 | obj.PayPrice[1] = (int)reader.ReadElementContentAsInt("PayPrice1", String.Empty); | ||
715 | } | ||
716 | |||
717 | private static void ProcessPayPrice2(SceneObjectPart obj, XmlTextReader reader) | ||
718 | { | ||
719 | obj.PayPrice[2] = (int)reader.ReadElementContentAsInt("PayPrice2", String.Empty); | ||
720 | } | ||
721 | |||
722 | private static void ProcessPayPrice3(SceneObjectPart obj, XmlTextReader reader) | ||
723 | { | ||
724 | obj.PayPrice[3] = (int)reader.ReadElementContentAsInt("PayPrice3", String.Empty); | ||
725 | } | ||
726 | |||
727 | private static void ProcessPayPrice4(SceneObjectPart obj, XmlTextReader reader) | ||
728 | { | ||
729 | obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); | ||
730 | } | ||
731 | |||
701 | #endregion | 732 | #endregion |
702 | 733 | ||
703 | #region TaskInventoryXmlProcessors | 734 | #region TaskInventoryXmlProcessors |
@@ -1069,7 +1100,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1069 | shp.Media = PrimitiveBaseShape.MediaList.FromXml(value); | 1100 | shp.Media = PrimitiveBaseShape.MediaList.FromXml(value); |
1070 | } | 1101 | } |
1071 | 1102 | ||
1072 | |||
1073 | #endregion | 1103 | #endregion |
1074 | 1104 | ||
1075 | ////////// Write ///////// | 1105 | ////////// Write ///////// |
@@ -1175,6 +1205,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1175 | writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); | 1205 | writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); |
1176 | WriteBytes(writer, "TextureAnimation", sop.TextureAnimation); | 1206 | WriteBytes(writer, "TextureAnimation", sop.TextureAnimation); |
1177 | WriteBytes(writer, "ParticleSystem", sop.ParticleSystem); | 1207 | WriteBytes(writer, "ParticleSystem", sop.ParticleSystem); |
1208 | writer.WriteElementString("PayPrice0", sop.PayPrice[0].ToString()); | ||
1209 | writer.WriteElementString("PayPrice1", sop.PayPrice[1].ToString()); | ||
1210 | writer.WriteElementString("PayPrice2", sop.PayPrice[2].ToString()); | ||
1211 | writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); | ||
1212 | writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); | ||
1178 | 1213 | ||
1179 | writer.WriteEndElement(); | 1214 | writer.WriteEndElement(); |
1180 | } | 1215 | } |
diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs index 8589901..7304145 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs | |||
@@ -95,8 +95,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance | |||
95 | scene.AddCommand( | 95 | scene.AddCommand( |
96 | this, "appearance show", | 96 | this, "appearance show", |
97 | "appearance show", | 97 | "appearance show", |
98 | "Show appearance information for each avatar in the simulator. At the moment, ", | 98 | "Show appearance information for each avatar in the simulator.", |
99 | ShowAppearanceInfo); | 99 | "At the moment this actually just checks that we have all the required baked textures. If not, then appearance is 'corrupt' and other avatars will continue to see a cloud.", |
100 | ShowAppearanceInfo); | ||
100 | } | 101 | } |
101 | 102 | ||
102 | protected void ShowAppearanceInfo(string module, string[] cmd) | 103 | protected void ShowAppearanceInfo(string module, string[] cmd) |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 1cf03b8..ce7d97c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -3316,12 +3316,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3316 | return m_ScriptEngine.GetStartParameter(m_itemID); | 3316 | return m_ScriptEngine.GetStartParameter(m_itemID); |
3317 | } | 3317 | } |
3318 | 3318 | ||
3319 | public void llGodLikeRezObject(string inventory, LSL_Vector pos) | ||
3320 | { | ||
3321 | m_host.AddScriptLPS(1); | ||
3322 | NotImplemented("llGodLikeRezObject"); | ||
3323 | } | ||
3324 | |||
3325 | public void llRequestPermissions(string agent, int perm) | 3319 | public void llRequestPermissions(string agent, int perm) |
3326 | { | 3320 | { |
3327 | UUID agentID = new UUID(); | 3321 | UUID agentID = new UUID(); |
@@ -3870,9 +3864,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3870 | throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); | 3864 | throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); |
3871 | } | 3865 | } |
3872 | 3866 | ||
3873 | // check if destination is an avatar | 3867 | // check if destination is an object |
3874 | if (World.GetScenePresence(destId) != null) | 3868 | if (World.GetSceneObjectPart(destId) != null) |
3875 | { | 3869 | { |
3870 | // destination is an object | ||
3871 | World.MoveTaskInventoryItem(destId, m_host, objId); | ||
3872 | } | ||
3873 | else | ||
3874 | { | ||
3875 | ScenePresence presence = World.GetScenePresence(destId); | ||
3876 | |||
3877 | if (presence == null) | ||
3878 | { | ||
3879 | UserAccount account = | ||
3880 | World.UserAccountService.GetUserAccount( | ||
3881 | World.RegionInfo.ScopeID, | ||
3882 | destId); | ||
3883 | |||
3884 | if (account == null) | ||
3885 | { | ||
3886 | llSay(0, "Can't find destination "+destId.ToString()); | ||
3887 | return; | ||
3888 | } | ||
3889 | } | ||
3876 | // destination is an avatar | 3890 | // destination is an avatar |
3877 | InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); | 3891 | InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); |
3878 | 3892 | ||
@@ -3893,16 +3907,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3893 | m_host.AbsolutePosition.ToString(), | 3907 | m_host.AbsolutePosition.ToString(), |
3894 | agentItem.ID, true, m_host.AbsolutePosition, | 3908 | agentItem.ID, true, m_host.AbsolutePosition, |
3895 | bucket); | 3909 | bucket); |
3896 | |||
3897 | if (m_TransferModule != null) | 3910 | if (m_TransferModule != null) |
3898 | m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); | 3911 | m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); |
3912 | ScriptSleep(3000); | ||
3899 | } | 3913 | } |
3900 | else | ||
3901 | { | ||
3902 | // destination is an object | ||
3903 | World.MoveTaskInventoryItem(destId, m_host, objId); | ||
3904 | } | ||
3905 | ScriptSleep(3000); | ||
3906 | } | 3914 | } |
3907 | 3915 | ||
3908 | public void llRemoveInventory(string name) | 3916 | public void llRemoveInventory(string name) |
@@ -4189,12 +4197,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4189 | m_host.CollisionSoundVolume = (float)impact_volume; | 4197 | m_host.CollisionSoundVolume = (float)impact_volume; |
4190 | } | 4198 | } |
4191 | 4199 | ||
4192 | public void llCollisionSprite(string impact_sprite) | ||
4193 | { | ||
4194 | m_host.AddScriptLPS(1); | ||
4195 | NotImplemented("llCollisionSprite"); | ||
4196 | } | ||
4197 | |||
4198 | public LSL_String llGetAnimation(string id) | 4200 | public LSL_String llGetAnimation(string id) |
4199 | { | 4201 | { |
4200 | // This should only return a value if the avatar is in the same region | 4202 | // This should only return a value if the avatar is in the same region |
@@ -5526,12 +5528,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5526 | ScriptSleep(100); | 5528 | ScriptSleep(100); |
5527 | } | 5529 | } |
5528 | 5530 | ||
5529 | public void llSetSoundQueueing(int queue) | ||
5530 | { | ||
5531 | m_host.AddScriptLPS(1); | ||
5532 | NotImplemented("llSetSoundQueueing"); | ||
5533 | } | ||
5534 | |||
5535 | public void llSetSoundRadius(double radius) | 5531 | public void llSetSoundRadius(double radius) |
5536 | { | 5532 | { |
5537 | m_host.AddScriptLPS(1); | 5533 | m_host.AddScriptLPS(1); |
@@ -10312,6 +10308,73 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10312 | 10308 | ||
10313 | return rq.ToString(); | 10309 | return rq.ToString(); |
10314 | } | 10310 | } |
10311 | |||
10312 | #region Not Implemented | ||
10313 | // | ||
10314 | // Listing the unimplemented lsl functions here, please move | ||
10315 | // them from this region as they are completed | ||
10316 | // | ||
10317 | public void llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) | ||
10318 | { | ||
10319 | m_host.AddScriptLPS(1); | ||
10320 | NotImplemented("llCastRay"); | ||
10321 | |||
10322 | } | ||
10323 | |||
10324 | public void llGetEnv(LSL_String name) | ||
10325 | { | ||
10326 | m_host.AddScriptLPS(1); | ||
10327 | NotImplemented("llGetEnv"); | ||
10328 | |||
10329 | } | ||
10330 | |||
10331 | public void llGetSPMaxMemory() | ||
10332 | { | ||
10333 | m_host.AddScriptLPS(1); | ||
10334 | NotImplemented("llGetSPMaxMemory"); | ||
10335 | |||
10336 | } | ||
10337 | |||
10338 | public void llGetUsedMemory() | ||
10339 | { | ||
10340 | m_host.AddScriptLPS(1); | ||
10341 | NotImplemented("llGetUsedMemory"); | ||
10342 | |||
10343 | } | ||
10344 | |||
10345 | public void llRegionSayTo( LSL_Key target, LSL_Integer channel, LSL_String msg ) | ||
10346 | { | ||
10347 | m_host.AddScriptLPS(1); | ||
10348 | NotImplemented("llRegionSayTo"); | ||
10349 | |||
10350 | } | ||
10351 | |||
10352 | public void llScriptProfiler( LSL_Integer flags ) | ||
10353 | { | ||
10354 | m_host.AddScriptLPS(1); | ||
10355 | NotImplemented("llScriptProfiler"); | ||
10356 | |||
10357 | } | ||
10358 | |||
10359 | public void llSetSoundQueueing(int queue) | ||
10360 | { | ||
10361 | m_host.AddScriptLPS(1); | ||
10362 | NotImplemented("llSetSoundQueueing"); | ||
10363 | } | ||
10364 | |||
10365 | public void llCollisionSprite(string impact_sprite) | ||
10366 | { | ||
10367 | m_host.AddScriptLPS(1); | ||
10368 | NotImplemented("llCollisionSprite"); | ||
10369 | } | ||
10370 | |||
10371 | public void llGodLikeRezObject(string inventory, LSL_Vector pos) | ||
10372 | { | ||
10373 | m_host.AddScriptLPS(1); | ||
10374 | NotImplemented("llGodLikeRezObject"); | ||
10375 | } | ||
10376 | |||
10377 | #endregion | ||
10315 | } | 10378 | } |
10316 | 10379 | ||
10317 | public class NotecardCache | 10380 | public class NotecardCache |
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 97ab411..d253c6a 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | |||
@@ -393,11 +393,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
393 | return 0; | 393 | return 0; |
394 | } | 394 | } |
395 | 395 | ||
396 | public object DoMaintenance(object p) | 396 | public void SaveAllState() |
397 | { | 397 | { |
398 | object[] parms = (object[])p; | ||
399 | int sleepTime = (int)parms[0]; | ||
400 | |||
401 | foreach (IScriptInstance inst in m_Scripts.Values) | 398 | foreach (IScriptInstance inst in m_Scripts.Values) |
402 | { | 399 | { |
403 | if (inst.EventTime() > m_EventLimit) | 400 | if (inst.EventTime() > m_EventLimit) |
@@ -407,6 +404,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
407 | inst.Start(); | 404 | inst.Start(); |
408 | } | 405 | } |
409 | } | 406 | } |
407 | } | ||
408 | |||
409 | public object DoMaintenance(object p) | ||
410 | { | ||
411 | object[] parms = (object[])p; | ||
412 | int sleepTime = (int)parms[0]; | ||
413 | |||
414 | SaveAllState(); | ||
410 | 415 | ||
411 | System.Threading.Thread.Sleep(sleepTime); | 416 | System.Threading.Thread.Sleep(sleepTime); |
412 | 417 | ||