diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 323d90c226..93201e1c8b 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -76,7 +76,7 @@ namespace OpenSim
///
/// The file used to load and save an opensim archive if no filename has been specified
///
- protected const string DEFAULT_OAR_BACKUP_FILENAME = "scene_oar.tar.gz";
+ protected const string DEFAULT_OAR_BACKUP_FILENAME = "scene.oar";
public ConfigSettings ConfigurationSettings
{
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveConstants.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveConstants.cs
index b274af230a..e2bce16650 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveConstants.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveConstants.cs
@@ -50,6 +50,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
///
public static readonly string ASSET_EXTENSION_SEPARATOR = "_";
+ ///
+ /// Used to separate components in an inventory node name
+ ///
+ public static readonly string INVENTORY_NODE_NAME_COMPONENT_SEPARATOR = "__";
+
///
/// Extensions used for asset types in the archive
///
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index fc639575ab..4a681bc19e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -85,7 +85,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
if (contents.Equals("")) return null;
- reader.ReadStartElement("InventoryObject");
+ reader.ReadStartElement("InventoryItem");
reader.ReadStartElement("Name");
item.Name = reader.ReadString();
reader.ReadEndElement();
@@ -138,10 +138,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
reader.ReadStartElement("GroupOwned");
item.GroupOwned = Convert.ToBoolean(reader.ReadString());
reader.ReadEndElement();
- //reader.ReadStartElement("ParentFolderID");
- //item.Folder = UUID.Parse(reader.ReadString());
- //reader.ReadEndElement();
- //reader.ReadEndElement();
return item;
}
@@ -187,13 +183,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
if (null == rootDestinationFolder)
{
- // TODO: Later on, automatically create this folder if it does not exist
+ // Possibly provide an option later on to automatically create this folder if it does not exist
m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath);
return nodesLoaded;
}
archive = new TarArchiveReader(m_loadStream);
+
+ // In order to load identically named folders, we need to keep track of the folders that we have already
+ // created
+ Dictionary foldersCreated = new Dictionary();
byte[] data;
TarArchiveReader.TarEntryType entryType;
@@ -222,12 +222,72 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
item.Creator = m_userInfo.UserProfile.ID;
item.Owner = m_userInfo.UserProfile.ID;
- filePath = filePath.Substring(InventoryArchiveConstants.INVENTORY_PATH.Length);
- filePath = filePath.Remove(filePath.LastIndexOf("/"));
+ string fsPath = filePath.Substring(InventoryArchiveConstants.INVENTORY_PATH.Length);
+ fsPath = fsPath.Remove(fsPath.LastIndexOf("/") + 1);
+ string originalFsPath = fsPath;
- m_log.DebugFormat("[INVENTORY ARCHIVER]: Loading to file path {0}", filePath);
+ m_log.DebugFormat("[INVENTORY ARCHIVER]: Loading to folder {0}", fsPath);
- string[] rawFolders = filePath.Split(new char[] { '/' });
+ InventoryFolderImpl foundFolder = null;
+ while (null == foundFolder && fsPath.Length > 0)
+ {
+ if (foldersCreated.ContainsKey(fsPath))
+ {
+ m_log.DebugFormat("[INVENTORY ARCHIVER]: Found previously created fs path {0}", fsPath);
+ foundFolder = foldersCreated[fsPath];
+ }
+ else
+ {
+ // Don't include the last slash
+ int penultimateSlashIndex = fsPath.LastIndexOf("/", fsPath.Length - 2);
+
+ if (penultimateSlashIndex >= 0)
+ {
+ fsPath = fsPath.Remove(penultimateSlashIndex + 1);
+ }
+ else
+ {
+ m_log.DebugFormat(
+ "[INVENTORY ARCHIVER]: Found no previously created fs path for {0}",
+ originalFsPath);
+ fsPath = string.Empty;
+ foundFolder = rootDestinationFolder;
+ }
+ }
+ }
+
+ string fsPathSectionToCreate = originalFsPath.Substring(fsPath.Length);
+ string[] rawDirsToCreate
+ = fsPathSectionToCreate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
+ int i = 0;
+
+ while (i < rawDirsToCreate.Length)
+ {
+ m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0}", rawDirsToCreate[i]);
+
+ int identicalNameIdentifierIndex
+ = rawDirsToCreate[i].LastIndexOf(
+ InventoryArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR);
+ string folderName = rawDirsToCreate[i].Remove(identicalNameIdentifierIndex);
+
+ UUID newFolderId = UUID.Random();
+ m_userInfo.CreateFolder(
+ folderName, newFolderId, (ushort)AssetType.Folder, foundFolder.ID);
+ foundFolder = foundFolder.GetChildFolder(newFolderId);
+
+ // Record that we have now created this folder
+ fsPath += rawDirsToCreate[i] + "/";
+ m_log.DebugFormat("[INVENTORY ARCHIVER]: Recording creation of fs path {0}", fsPath);
+ foldersCreated[fsPath] = foundFolder;
+
+ if (0 == i)
+ nodesLoaded.Add(foundFolder);
+
+ i++;
+ }
+
+ /*
+ string[] rawFolders = filePath.Split(new char[] { '/' });
// Find the folders that do exist along the path given
int i = 0;
@@ -257,16 +317,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
m_userInfo.CreateFolder(
rawFolders[i++], newFolderId, (ushort)AssetType.Folder, foundFolder.ID);
foundFolder = foundFolder.GetChildFolder(newFolderId);
- }
+ }
+ */
// Reset folder ID to the one in which we want to load it
item.Folder = foundFolder.ID;
-
- //item.Folder = rootDestinationFolder.ID;
m_userInfo.AddItem(item);
successfulItemRestores++;
- nodesLoaded.Add(item);
+
+ // If we're loading an item directly into the given destination folder then we need to record
+ // it separately from any loaded root folders
+ if (rootDestinationFolder == foundFolder)
+ nodesLoaded.Add(item);
}
}
}
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index 2b071f066a..357ed401cb 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -106,14 +106,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
m_module.TriggerInventoryArchiveSaved(succeeded, m_userInfo, m_invPath, m_saveStream, reportedException);
}
- protected void saveInvItem(InventoryItemBase inventoryItem, string path)
+ protected void SaveInvItem(InventoryItemBase inventoryItem, string path)
{
string filename = string.Format("{0}{1}_{2}.xml", path, inventoryItem.Name, inventoryItem.ID);
StringWriter sw = new StringWriter();
XmlTextWriter writer = new XmlTextWriter(sw);
writer.Formatting = Formatting.Indented;
- writer.WriteStartElement("InventoryObject");
+ writer.WriteStartElement("InventoryItem");
+
writer.WriteStartElement("Name");
writer.WriteString(inventoryItem.Name);
writer.WriteEndElement();
@@ -168,9 +169,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
writer.WriteStartElement("GroupOwned");
writer.WriteString(inventoryItem.GroupOwned.ToString());
writer.WriteEndElement();
- writer.WriteStartElement("ParentFolderID");
- writer.WriteString(inventoryItem.Folder.ToString());
- writer.WriteEndElement();
+
writer.WriteEndElement();
archive.AddFile(filename, sw.ToString());
@@ -178,20 +177,48 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, assetUuids);
}
- protected void saveInvDir(InventoryFolderImpl inventoryFolder, string path)
+ protected void SaveInvDir(InventoryFolderImpl inventoryFolder, string path)
{
- List inventories = inventoryFolder.RequestListOfFolderImpls();
- List items = inventoryFolder.RequestListOfItems();
- string newPath = path + inventoryFolder.Name + InventoryFolderImpl.PATH_DELIMITER;
- archive.AddDir(newPath);
+ path +=
+ string.Format(
+ "{0}{1}{2}/",
+ inventoryFolder.Name,
+ InventoryArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR,
+ inventoryFolder.ID);
+ archive.AddDir(path);
+
+ List childFolders = inventoryFolder.RequestListOfFolderImpls();
+ List items = inventoryFolder.RequestListOfItems();
+
+ /*
+ Dictionary identicalFolderNames = new Dictionary();
foreach (InventoryFolderImpl folder in inventories)
{
- saveInvDir(folder, newPath);
+
+ if (!identicalFolderNames.ContainsKey(folder.Name))
+ identicalFolderNames[folder.Name] = 0;
+ else
+ identicalFolderNames[folder.Name] = identicalFolderNames[folder.Name]++;
+
+ int folderNameNumber = identicalFolderName[folder.Name];
+
+ SaveInvDir(
+ folder,
+ string.Format(
+ "{0}{1}{2}/",
+ path, InventoryArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, folderNameNumber));
}
+ */
+
+ foreach (InventoryFolderImpl childFolder in childFolders)
+ {
+ SaveInvDir(childFolder, path);
+ }
+
foreach (InventoryItemBase item in items)
{
- saveInvItem(item, newPath);
+ SaveInvItem(item, path);
}
}
@@ -270,7 +297,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
inventoryItem.Name, inventoryItem.ID, m_invPath);
//get and export item info
- saveInvItem(inventoryItem, m_invPath);
+ SaveInvItem(inventoryItem, m_invPath);
}
}
else
@@ -280,7 +307,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
inventoryFolder.Name, inventoryFolder.ID, m_invPath);
//recurse through all dirs getting dirs and files
- saveInvDir(inventoryFolder, InventoryArchiveConstants.INVENTORY_PATH);
+ SaveInvDir(inventoryFolder, InventoryArchiveConstants.INVENTORY_PATH);
}
new AssetsRequest(assetUuids.Keys, m_module.CommsManager.AssetCache, ReceivedAllAssets).Execute();
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
index cb613f7e9a..5cc03406f9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
@@ -124,15 +124,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
MemoryStream archiveReadStream = new MemoryStream(archive);
TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
+ InventoryFolderImpl objectsFolder = userInfo.RootFolder.FindFolderByPath("Objects");
+
//bool gotControlFile = false;
bool gotObject1File = false;
//bool gotObject2File = false;
string expectedObject1FilePath = string.Format(
- "{0}{1}{2}_{3}.xml",
+ "{0}{1}/{2}_{3}.xml",
InventoryArchiveConstants.INVENTORY_PATH,
- "Objects/",
+ string.Format(
+ "Objects{0}{1}", InventoryArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, objectsFolder.ID),
item1.Name,
item1Id);
+
/*
string expectedObject2FileName = string.Format(
"{0}_{1:000}-{2:000}-{3:000}__{4}.xml",
@@ -146,6 +150,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
while (tar.ReadEntry(out filePath, out tarEntryType) != null)
{
+ Console.WriteLine("Got {0}", filePath);
+
/*
if (ArchiveConstants.CONTROL_FILE_PATH == filePath)
{
@@ -153,7 +159,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
}
*/
if (filePath.StartsWith(InventoryArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml"))
- {
+ {
//string fileName = filePath.Remove(0, "Objects/".Length);
//if (fileName.StartsWith(part1.Name))
diff --git a/OpenSim/Region/CoreModules/World/Archiver/TarArchiveReader.cs b/OpenSim/Region/CoreModules/World/Archiver/TarArchiveReader.cs
index afe59382d1..19d2629d3e 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/TarArchiveReader.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/TarArchiveReader.cs
@@ -89,22 +89,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
return null;
entryType = header.EntryType;
- filePath = header.FilePath;
- byte[] data = m_br.ReadBytes(header.FileSize);
-
- //m_log.DebugFormat("[TAR ARCHIVE READER]: filePath {0}, fileSize {1}", filePath, header.FileSize);
-
- // Read the rest of the empty padding in the 512 byte block
- if (header.FileSize % 512 != 0)
- {
- int paddingLeft = 512 - (header.FileSize % 512);
-
- //m_log.DebugFormat("[TAR ARCHIVE READER]: Reading {0} padding bytes", paddingLeft);
-
- m_br.ReadBytes(paddingLeft);
- }
-
- return data;
+ filePath = header.FilePath;
+ return ReadData(header.FileSize);
}
///
@@ -126,7 +112,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
if (header[156] == (byte)'L')
{
int longNameLength = ConvertOctalBytesToDecimal(header, 124, 11);
- tarHeader.FilePath = m_asciiEncoding.GetString(m_br.ReadBytes(longNameLength));
+ tarHeader.FilePath = m_asciiEncoding.GetString(ReadData(longNameLength));
m_log.DebugFormat("[TAR ARCHIVE READER]: Got long file name {0}", tarHeader.FilePath);
header = m_br.ReadBytes(512);
}
@@ -134,6 +120,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
{
tarHeader.FilePath = m_asciiEncoding.GetString(header, 0, 100);
tarHeader.FilePath = tarHeader.FilePath.Trim(m_nullCharArray);
+ m_log.DebugFormat("[TAR ARCHIVE READER]: Got short file name {0}", tarHeader.FilePath);
}
tarHeader.FileSize = ConvertOctalBytesToDecimal(header, 124, 11);
@@ -171,6 +158,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver
return tarHeader;
}
+
+ ///
+ /// Read data following a header
+ ///
+ ///
+ ///
+ protected byte[] ReadData(int fileSize)
+ {
+ byte[] data = m_br.ReadBytes(fileSize);
+
+ m_log.DebugFormat("[TAR ARCHIVE READER]: fileSize {0}", fileSize);
+
+ // Read the rest of the empty padding in the 512 byte block
+ if (fileSize % 512 != 0)
+ {
+ int paddingLeft = 512 - (fileSize % 512);
+
+ m_log.DebugFormat("[TAR ARCHIVE READER]: Reading {0} padding bytes", paddingLeft);
+
+ m_br.ReadBytes(paddingLeft);
+ }
+
+ return data;
+ }
public void Close()
{