bool DearchiveRegion0DotStar ()
{
if (m_loadStream == null)
return false;
int successfulAssetRestores = 0;
int failedAssetRestores = 0;
string filePath = "NONE";
DateTime start = DateTime.Now;
TarArchiveReader archive = new TarArchiveReader (m_loadStream);
if (!m_skipAssets)
m_threadpool = new UniverseThreadPool (
new UniverseThreadPoolStartInfo () {
Threads = 1,
priority = System.Threading.ThreadPriority.BelowNormal
});
IBackupModule backup = m_scene.RequestModuleInterface<IBackupModule> ();
if (!m_merge) {
DateTime before = DateTime.Now;
MainConsole.Instance.Info ("[Archiver]: Clearing all existing scene objects");
if (backup != null)
backup.DeleteAllSceneObjects ();
MainConsole.Instance.Info ("[Archiver]: Cleared all existing scene objects in " +
(DateTime.Now - before).Minutes + ":" + (DateTime.Now - before).Seconds);
}
IScriptModule [] modules = m_scene.RequestModuleInterfaces<IScriptModule> ();
//Disable the script engine so that it doesn't load in the background and kill OAR loading
foreach (IScriptModule module in modules) {
module.Disabled = true;
}
//Disable backup for now as well
if (backup != null)
backup.LoadingPrims = true;
IRegionSerializerModule serializer = m_scene.RequestModuleInterface<IRegionSerializerModule> ();
int sceneObjectsLoadedCount = 0;
//We save the groups so that we can back them up later
List<ISceneEntity> groupsToBackup = new List<ISceneEntity> ();
List<LandData> landData = new List<LandData> ();
// must save off some stuff until after assets have been saved and received new uuids
// keeping these collection local because I am sure they will get large and garbage collection is better that way
List<byte []> seneObjectGroups = new List<byte []> ();
Dictionary<UUID, UUID> assetBinaryChangeRecord = new Dictionary<UUID, UUID> ();
Queue<UUID> assets2Save = new Queue<UUID> ();
MainConsole.Instance.Info ("[Archiver]: Commencing load from archive");
int ticker = 0;
try {
byte [] data;
TarArchiveReader.TarEntryType entryType;
while ((data = archive.ReadEntry (out filePath, out entryType)) != null) {
if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
continue;
if (TarArchiveReader.TarEntryType.TYPE_NORMAL_FILE == entryType) {
string fName;
try {
fName = Path.GetFileName (filePath);
if (fName.StartsWith (".", StringComparison.Ordinal)) // ignore hidden files
continue;
} catch {
MainConsole.Instance.ErrorFormat ("[Archiver]: Invalid file name in archive: {0}", filePath);
continue;
}
}
ticker++;
if (ticker % 10 == 0)
MainConsole.Instance.Ticker ();
if (filePath.StartsWith (ArchiveConstants.OBJECTS_PATH, StringComparison.Ordinal)) {
seneObjectGroups.Add (data);
if (seneObjectGroups.Count % 100 == 0)
MainConsole.Instance.Ticker (
string.Format("[Archiver]: Found {0} scene object groups...", seneObjectGroups.Count) , true);
} else if (!m_skipAssets && filePath.StartsWith (ArchiveConstants.ASSETS_PATH, StringComparison.Ordinal)) {
AssetBase asset;
if (LoadAsset (filePath, data, out asset)) {
successfulAssetRestores++;
if (m_useAsync)
lock (AssetsToAdd) AssetsToAdd.Add (asset);
else {
if (asset.IsBinaryAsset) {
UUID aid = asset.ID;
asset.ID = m_scene.AssetService.Store (asset);
if (asset.ID != aid && asset.ID != UUID.Zero)
assetBinaryChangeRecord.Add (aid, asset.ID);
} else {
if (!assetNonBinaryCollection.ContainsKey (asset.ID)) {
assetNonBinaryCollection.Add (asset.ID, asset);
// I need something I can safely loop through
assets2Save.Enqueue (asset.ID);
}
}
}
} else
failedAssetRestores++;
if ((successfulAssetRestores + failedAssetRestores) % 100 == 0)
MainConsole.Instance.Ticker(
string.Format("[Archiver]: Loaded {0} assets, with {1} failures...",
successfulAssetRestores, failedAssetRestores),
true);
} else if (!m_skipTerrain && filePath.StartsWith (ArchiveConstants.TERRAINS_PATH, StringComparison.Ordinal)) {
LoadTerrain (filePath, data);
} else if (!m_merge && filePath.StartsWith (ArchiveConstants.SETTINGS_PATH, StringComparison.Ordinal)) {
LoadRegionSettings (filePath, data);
} else if (!m_skipTerrain && filePath.StartsWith (ArchiveConstants.LANDDATA_PATH, StringComparison.Ordinal)) {
var parcel = LoadLandData (data);
landData.Add (parcel);
} else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) {
LoadControlFile (data);
}
}
MainConsole.Instance.CleanInfo ("");
MainConsole.Instance.Info ("[Archiver]: Saving non binary assets");
ticker = 0;
// Save Assets
int savingAssetsCount = 0;
while (assets2Save.Count > 0) {
ticker++;
if (ticker % 10 == 0)
MainConsole.Instance.Ticker ();
try {
UUID assetid = assets2Save.Dequeue ();
SaveNonBinaryAssets (assetid, assetNonBinaryCollection [assetid], assetBinaryChangeRecord);
savingAssetsCount++;
if ((savingAssetsCount) % 100 == 0)
MainConsole.Instance.Ticker (
string.Format("[Archiver]: Saved {0} assets...", savingAssetsCount),true);
} catch (Exception ex) {
MainConsole.Instance.Info ("[Archiver]: Exception in saving an asset: " + ex);
}
}
MainConsole.Instance.CleanInfo ("");
MainConsole.Instance.Info ("[Archiver]: Saving loaded objects");
ticker = 0;
foreach (byte [] data2 in seneObjectGroups) {
ticker++;
if (ticker % 10 == 0)
MainConsole.Instance.Ticker ();
byte [] data3 = data2;
string stringData = Utils.BytesToString (data3);
MatchCollection mc = Regex.Matches (stringData, sPattern);
bool didChange = false;
if (mc.Count >= 1) {
foreach (Match match in mc) {
UUID thematch = new UUID (match.Value);
UUID newvalue = thematch;
if (assetNonBinaryCollection.ContainsKey (thematch))
newvalue = assetNonBinaryCollection [thematch].ID;
else if (assetBinaryChangeRecord.ContainsKey (thematch))
newvalue = assetBinaryChangeRecord [thematch];
if (thematch == newvalue) continue;
stringData = stringData.Replace (thematch.ToString ().Trim (), newvalue.ToString ().Trim ());
didChange = true;
}
}
if (didChange)
data3 = Utils.StringToBytes (stringData);
ISceneEntity sceneObject = serializer.DeserializeGroupFromXml2 (data3, m_scene);
if (sceneObject == null) {
//! big error!
MainConsole.Instance.Error ("Error reading SOP XML (Please mantis this!): " +
m_asciiEncoding.GetString (data3));
continue;
}
// check sceneObject ownership
sceneObject.OwnerID = ResolveUserUuid (sceneObject.OwnerID, sceneObject.LastSignificantPosition, landData);
//... and children
foreach (ISceneChildEntity part in sceneObject.ChildrenEntities ()) {
// check user ID's
part.CreatorID = ResolveUserUuid (part.CreatorID, part.AbsolutePosition, landData);
part.OwnerID = ResolveUserUuid (part.OwnerID, part.AbsolutePosition, landData);
part.LastOwnerID = ResolveUserUuid (part.LastOwnerID, part.AbsolutePosition, landData);
//check group ID's
part.GroupID = ResolveGroupUuid (part.GroupID);
// And zap any troublesome sit target information
part.SitTargetOrientation = new Quaternion (0, 0, 0, 1);
part.SitTargetPosition = new Vector3 (0, 0, 0);
// Fix ownership/creator of inventory items
// Not doing so results in inventory items
// being no copy/no mod for everyone
lock (part.TaskInventory) {
TaskInventoryDictionary inv = part.TaskInventory;
foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) {
// check user ID's
kvp.Value.OwnerID = ResolveUserUuid (
kvp.Value.OwnerID,
part.AbsolutePosition,
landData
);
kvp.Value.LastOwnerID = ResolveUserUuid (
kvp.Value.LastOwnerID,
part.AbsolutePosition,
landData
);
kvp.Value.CreatorID = ResolveUserUuid (
kvp.Value.CreatorID,
part.AbsolutePosition,
landData
);
// ..and possible group ID's
kvp.Value.GroupID = ResolveGroupUuid (kvp.Value.GroupID);
}
}
}
//Add the offsets of the region
Vector3 newPos = new Vector3 (sceneObject.AbsolutePosition.X + m_offsetX,
sceneObject.AbsolutePosition.Y + m_offsetY,
sceneObject.AbsolutePosition.Z + m_offsetZ);
if (m_flipX)
newPos.X = m_scene.RegionInfo.RegionSizeX - newPos.X;
if (m_flipY)
newPos.Y = m_scene.RegionInfo.RegionSizeY - newPos.Y;
sceneObject.SetAbsolutePosition (false, newPos);
if (m_scene.SceneGraph.AddPrimToScene (sceneObject)) {
groupsToBackup.Add (sceneObject);
sceneObject.ScheduleGroupUpdate (PrimUpdateFlags.ForcedFullUpdate);
sceneObject.CreateScriptInstances (0, false, StateSource.RegionStart, UUID.Zero, true);
}
sceneObjectsLoadedCount++;
if (sceneObjectsLoadedCount % 100 == 0)
MainConsole.Instance.Ticker (
string.Format("[Archiver]: Saved {0} objects...", sceneObjectsLoadedCount), true);
}
assetNonBinaryCollection.Clear ();
assetBinaryChangeRecord.Clear ();
seneObjectGroups.Clear ();
} catch (Exception e) {
MainConsole.Instance.ErrorFormat (
"[Archiver]: Aborting load with error in archive file {0}. {1}", filePath, e);
m_errorMessage += e.ToString ();
m_scene.EventManager.TriggerOarFileLoaded (UUID.Zero.Guid, m_errorMessage);
return false;
} finally {
archive.Close ();
m_loadStream.Close ();
m_loadStream.Dispose ();
assets2Save.Clear ();
assetNonBinaryCollection.Clear ();
// Re-enable scripts now that we are done
foreach (IScriptModule module in modules) {
module.Disabled = false;
}
// Reset backup too
if (backup != null)
backup.LoadingPrims = false;
}
// finished with the ticker
MainConsole.Instance.CleanInfo ("");
// Now back up the prims
foreach (ISceneEntity grp in groupsToBackup) {
// Backup!
grp.HasGroupChanged = true;
}
if (!m_skipAssets && m_useAsync && !AssetSaverIsRunning)
m_threadpool.QueueEvent (SaveAssets, 0);
if (!m_skipAssets) {
MainConsole.Instance.InfoFormat ("[Archiver]: Restored {0} assets", successfulAssetRestores);
if (failedAssetRestores > 0) {
MainConsole.Instance.ErrorFormat ("[Archiver]: Failed to load {0} assets", failedAssetRestores);
m_errorMessage += string.Format ("Failed to load {0} assets", failedAssetRestores);
}
}
// Reload serialized parcels
if (!m_skipTerrain) {
MainConsole.Instance.InfoFormat ("[Archiver]: Loading {0} parcels.", landData.Count);
IParcelManagementModule parcelManagementModule = m_scene.RequestModuleInterface<IParcelManagementModule> ();
if (parcelManagementModule != null)
parcelManagementModule.IncomingLandDataFromOAR (landData, m_merge, new Vector2 (m_offsetX, m_offsetY));
MainConsole.Instance.InfoFormat ("[Archiver]: Restored {0} parcels.", landData.Count);
}
// Clean it out
landData.Clear ();
MainConsole.Instance.InfoFormat ("[Archiver]: Successfully loaded archive in " +
(DateTime.Now - start).Minutes + ":" + (DateTime.Now - start).Seconds);
m_validUserUuids.Clear ();
m_validGroupUuids.Clear ();
m_scene.EventManager.TriggerOarFileLoaded (UUID.Zero.Guid, m_errorMessage);
return true; // all good
}