* Add the abilty to load and save iar item nodes where folders have identical names
parent
e57ac6e0bf
commit
b52ac542ad
|
@ -76,7 +76,7 @@ namespace OpenSim
|
|||
/// <summary>
|
||||
/// The file used to load and save an opensim archive if no filename has been specified
|
||||
/// </summary>
|
||||
protected const string DEFAULT_OAR_BACKUP_FILENAME = "scene_oar.tar.gz";
|
||||
protected const string DEFAULT_OAR_BACKUP_FILENAME = "scene.oar";
|
||||
|
||||
public ConfigSettings ConfigurationSettings
|
||||
{
|
||||
|
|
|
@ -50,6 +50,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
|
|||
/// </summary>
|
||||
public static readonly string ASSET_EXTENSION_SEPARATOR = "_";
|
||||
|
||||
/// <summary>
|
||||
/// Used to separate components in an inventory node name
|
||||
/// </summary>
|
||||
public static readonly string INVENTORY_NODE_NAME_COMPONENT_SEPARATOR = "__";
|
||||
|
||||
/// <summary>
|
||||
/// Extensions used for asset types in the archive
|
||||
/// </summary>
|
||||
|
|
|
@ -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 <string, InventoryFolderImpl> foldersCreated = new Dictionary<string, InventoryFolderImpl>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<InventoryFolderImpl> inventories = inventoryFolder.RequestListOfFolderImpls();
|
||||
List<InventoryItemBase> 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<InventoryFolderImpl> childFolders = inventoryFolder.RequestListOfFolderImpls();
|
||||
List<InventoryItemBase> items = inventoryFolder.RequestListOfItems();
|
||||
|
||||
/*
|
||||
Dictionary identicalFolderNames = new Dictionary<string, int>();
|
||||
|
||||
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();
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read data following a header
|
||||
/// </summary>
|
||||
/// <param name="fileSize"></param>
|
||||
/// <returns></returns>
|
||||
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()
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue