This commit is contained in:
UbitUmarov
2017-07-20 11:30:12 +01:00
60 changed files with 2493 additions and 41860 deletions

View File

@@ -181,11 +181,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// Archive the regions
Dictionary<UUID, sbyte> assetUuids = new Dictionary<UUID, sbyte>();
HashSet<UUID> failedIDs = new HashSet<UUID>();
HashSet<UUID> uncertainAssetsUUIDs = new HashSet<UUID>();
scenesGroup.ForEachScene(delegate(Scene scene)
{
string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : "";
ArchiveOneRegion(scene, regionDir, assetUuids);
ArchiveOneRegion(scene, regionDir, assetUuids, failedIDs, uncertainAssetsUUIDs);
});
// Archive the assets
@@ -193,23 +195,21 @@ namespace OpenSim.Region.CoreModules.World.Archiver
if (SaveAssets)
{
m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count);
// Asynchronously request all the assets required to perform this archive operation
AssetsRequest ar
= new AssetsRequest(
AssetsRequest ar = new AssetsRequest(
new AssetsArchiver(m_archiveWriter), assetUuids,
failedIDs.Count,
m_rootScene.AssetService, m_rootScene.UserAccountService,
m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets);
WorkManager.RunInThread(o => ar.Execute(), null, "Archive Assets Request");
// CloseArchive() will be called from ReceivedAllAssets()
m_rootScene.RegionInfo.ScopeID, options, null);
ar.Execute();
assetUuids = null;
}
else
{
m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
CloseArchive(string.Empty);
// CloseArchive(string.Empty);
}
CloseArchive(string.Empty);
}
catch (Exception e)
{
@@ -218,7 +218,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
}
}
private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, sbyte> assetUuids)
private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, sbyte> assetUuids,
HashSet<UUID> failedIDs, HashSet<UUID> uncertainAssetsUUIDs)
{
m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.Name);
@@ -237,7 +238,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
{
SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
if (!sceneObject.IsDeleted && !sceneObject.IsAttachment)
if (!sceneObject.IsDeleted && !sceneObject.IsAttachment && !sceneObject.IsTemporary && !sceneObject.inTransit)
{
if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, FilterContent, permissionsModule))
{
@@ -254,17 +255,39 @@ namespace OpenSim.Region.CoreModules.World.Archiver
if (SaveAssets)
{
UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService, assetUuids);
UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService, assetUuids, failedIDs, uncertainAssetsUUIDs);
int prevAssets = assetUuids.Count;
foreach (SceneObjectGroup sceneObject in sceneObjects)
{
int curErrorCntr = assetGatherer.ErrorCount;
int possible = assetGatherer.possibleNotAssetCount;
assetGatherer.AddForInspection(sceneObject);
assetGatherer.GatherAll();
curErrorCntr = assetGatherer.ErrorCount - curErrorCntr;
possible = assetGatherer.possibleNotAssetCount - possible;
if(curErrorCntr > 0)
{
m_log.ErrorFormat("[ARCHIVER]: object {0} '{1}', at {2}, contains {3} references to missing or damaged assets",
sceneObject.UUID, sceneObject.Name ,sceneObject.AbsolutePosition.ToString(), curErrorCntr);
if(possible > 0)
m_log.WarnFormat("[ARCHIVER Warning]: object also contains {0} references that may be to missing or damaged assets or not a problem", possible);
}
else if(possible > 0)
{
m_log.WarnFormat("[ARCHIVER Warning]: object {0} '{1}', at {2}, contains {3} references that may be to missing or damaged assets or not a problem",
sceneObject.UUID, sceneObject.Name ,sceneObject.AbsolutePosition.ToString(), possible);
}
}
assetGatherer.GatherAll();
int errors = assetGatherer.FailedUUIDs.Count;
m_log.DebugFormat(
"[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets",
sceneObjects.Count, assetUuids.Count - prevAssets);
"[ARCHIVER]: {0} region scene objects to save reference {1} possible assets",
sceneObjects.Count, assetUuids.Count - prevAssets + errors);
if(errors > 0)
m_log.DebugFormat("[ARCHIVER]: {0} of these have problems or are not assets and will be ignored", errors);
}
if (numObjectsSkippedPermissions > 0)
@@ -572,7 +595,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
foreach (SceneObjectGroup sceneObject in sceneObjects)
{
//m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType());
if(sceneObject.IsDeleted || sceneObject.inTransit)
continue;
string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options);
string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject));
m_archiveWriter.WriteFile(objectPath, serializedObject);

View File

@@ -46,7 +46,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
/// <value>
/// Post a message to the log every x assets as a progress bar
/// </value>
protected static int LOG_ASSET_LOAD_NOTIFICATION_INTERVAL = 50;
protected static int LOG_ASSET_LOAD_NOTIFICATION_INTERVAL = 100;
/// <value>
/// Keep a count of the number of assets written so that we can provide status updates

View File

@@ -61,28 +61,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
Aborted
};
/// <value>
/// Timeout threshold if we still need assets or missing asset notifications but have stopped receiving them
/// from the asset service
/// </value>
protected const int TIMEOUT = 60 * 1000;
/// <value>
/// If a timeout does occur, limit the amount of UUID information put to the console.
/// </value>
protected const int MAX_UUID_DISPLAY_ON_TIMEOUT = 3;
protected System.Timers.Timer m_requestCallbackTimer;
/// <value>
/// State of this request
/// </value>
private RequestState m_requestState = RequestState.Initial;
/// <value>
/// uuids to request
/// </value>
protected IDictionary<UUID, sbyte> m_uuids;
private int m_previousErrorsCount;
/// <value>
/// Callback used when all the assets requested have been received.
@@ -104,6 +87,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
/// </value>
private int m_repliesRequired;
private System.Timers.Timer m_timeOutTimer;
private bool m_timeout;
/// <value>
/// Asset service used to request the assets
/// </value>
@@ -117,205 +103,98 @@ namespace OpenSim.Region.CoreModules.World.Archiver
protected internal AssetsRequest(
AssetsArchiver assetsArchiver, IDictionary<UUID, sbyte> uuids,
int previousErrorsCount,
IAssetService assetService, IUserAccountService userService,
UUID scope, Dictionary<string, object> options,
AssetsRequestCallback assetsRequestCallback)
{
m_assetsArchiver = assetsArchiver;
m_uuids = uuids;
m_previousErrorsCount = previousErrorsCount;
m_assetsRequestCallback = assetsRequestCallback;
m_assetService = assetService;
m_userAccountService = userService;
m_scopeID = scope;
m_options = options;
m_repliesRequired = uuids.Count;
// FIXME: This is a really poor way of handling the timeout since it will always leave the original requesting thread
// hanging. Need to restructure so an original request thread waits for a ManualResetEvent on asset received
// so we can properly abort that thread. Or request all assets synchronously, though that would be a more
// radical change
m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT);
m_requestCallbackTimer.AutoReset = false;
m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout);
}
protected internal void Execute()
{
m_requestState = RequestState.Running;
m_log.DebugFormat("[ARCHIVER]: AssetsRequest executed looking for {0} possible assets", m_repliesRequired);
Culture.SetCurrentCulture();
// We can stop here if there are no assets to fetch
if (m_repliesRequired == 0)
{
m_requestState = RequestState.Completed;
PerformAssetsRequestCallback(false);
return;
}
m_requestCallbackTimer.Enabled = true;
m_timeOutTimer = new System.Timers.Timer(60000);
m_timeOutTimer .AutoReset = false;
m_timeOutTimer.Elapsed += OnTimeout;
m_timeout = false;
foreach (KeyValuePair<UUID, sbyte> kvp in m_uuids)
{
// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key);
// m_assetService.Get(kvp.Key.ToString(), kvp.Value, PreAssetRequestCallback);
AssetBase asset = m_assetService.Get(kvp.Key.ToString());
PreAssetRequestCallback(kvp.Key.ToString(), kvp.Value, asset);
}
}
protected void OnRequestCallbackTimeout(object source, ElapsedEventArgs args)
{
bool timedOut = true;
try
{
lock (this)
string thiskey = kvp.Key.ToString();
try
{
// Take care of the possibilty that this thread started but was paused just outside the lock before
// the final request came in (assuming that such a thing is possible)
if (m_requestState == RequestState.Completed)
{
timedOut = false;
return;
}
m_requestState = RequestState.Aborted;
}
// Calculate which uuids were not found. This is an expensive way of doing it, but this is a failure
// case anyway.
List<UUID> uuids = new List<UUID>();
foreach (UUID uuid in m_uuids.Keys)
{
uuids.Add(uuid);
}
foreach (UUID uuid in m_foundAssetUuids)
{
uuids.Remove(uuid);
}
foreach (UUID uuid in m_notFoundAssetUuids)
{
uuids.Remove(uuid);
}
m_log.ErrorFormat(
"[ARCHIVER]: Asset service failed to return information about {0} requested assets", uuids.Count);
int i = 0;
foreach (UUID uuid in uuids)
{
m_log.ErrorFormat("[ARCHIVER]: No information about asset {0} received", uuid);
if (++i >= MAX_UUID_DISPLAY_ON_TIMEOUT)
m_timeOutTimer.Enabled = true;
AssetBase asset = m_assetService.Get(thiskey);
if(m_timeout)
break;
m_timeOutTimer.Enabled = false;
if(asset == null)
{
m_notFoundAssetUuids.Add(new UUID(thiskey));
continue;
}
sbyte assetType = kvp.Value;
if (asset != null && assetType == (sbyte)AssetType.Unknown)
{
m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", thiskey, SLUtil.AssetTypeFromCode(assetType));
asset.Type = assetType;
}
m_foundAssetUuids.Add(asset.FullID);
m_assetsArchiver.WriteAsset(PostProcess(asset));
}
if (uuids.Count > MAX_UUID_DISPLAY_ON_TIMEOUT)
m_log.ErrorFormat(
"[ARCHIVER]: (... {0} more not shown)", uuids.Count - MAX_UUID_DISPLAY_ON_TIMEOUT);
m_log.Error("[ARCHIVER]: Archive save aborted. PLEASE DO NOT USE THIS ARCHIVE, IT WILL BE INCOMPLETE.");
}
catch (Exception e)
{
m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}{1}", e.Message, e.StackTrace);
}
finally
{
if (timedOut)
WorkManager.RunInThread(PerformAssetsRequestCallback, true, "Archive Assets Request Callback");
}
}
protected void PreAssetRequestCallback(string fetchedAssetID, object assetType, AssetBase fetchedAsset)
{
// Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer
if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown)
{
m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, SLUtil.AssetTypeFromCode((sbyte)assetType));
fetchedAsset.Type = (sbyte)assetType;
}
AssetRequestCallback(fetchedAssetID, this, fetchedAsset);
}
/// <summary>
/// Called back by the asset cache when it has the asset
/// </summary>
/// <param name="assetID"></param>
/// <param name="asset"></param>
public void AssetRequestCallback(string id, object sender, AssetBase asset)
{
Culture.SetCurrentCulture();
try
{
lock (this)
catch (Exception e)
{
//m_log.DebugFormat("[ARCHIVER]: Received callback for asset {0}", id);
m_requestCallbackTimer.Stop();
if ((m_requestState == RequestState.Aborted) || (m_requestState == RequestState.Completed))
{
m_log.WarnFormat(
"[ARCHIVER]: Received information about asset {0} while in state {1}. Ignoring.",
id, m_requestState);
return;
}
if (asset != null)
{
// m_log.DebugFormat("[ARCHIVER]: Writing asset {0}", id);
m_foundAssetUuids.Add(asset.FullID);
m_assetsArchiver.WriteAsset(PostProcess(asset));
}
else
{
// m_log.DebugFormat("[ARCHIVER]: Recording asset {0} as not found", id);
m_notFoundAssetUuids.Add(new UUID(id));
}
if (m_foundAssetUuids.Count + m_notFoundAssetUuids.Count >= m_repliesRequired)
{
m_requestState = RequestState.Completed;
if(m_notFoundAssetUuids.Count == 0)
m_log.DebugFormat(
"[ARCHIVER]: Successfully added {0} assets",
m_foundAssetUuids.Count);
else
m_log.DebugFormat(
"[ARCHIVER]: Successfully added {0} assets ({1} assets not found but these may be expected invalid references)",
m_foundAssetUuids.Count, m_notFoundAssetUuids.Count);
// We want to stop using the asset cache thread asap
// as we now need to do the work of producing the rest of the archive
WorkManager.RunInThread(PerformAssetsRequestCallback, false, "Archive Assets Request Callback");
}
else
{
m_requestCallbackTimer.Start();
}
m_log.ErrorFormat("[ARCHIVER]: Execute failed with {0}", e);
}
}
catch (Exception e)
{
m_log.ErrorFormat("[ARCHIVER]: AssetRequestCallback failed with {0}", e);
}
m_timeOutTimer.Dispose();
int totalerrors = m_notFoundAssetUuids.Count + m_previousErrorsCount;
if(m_timeout)
m_log.DebugFormat("[ARCHIVER]: Aborted because AssetService request timeout. Successfully added {0} assets", m_foundAssetUuids.Count);
else if(totalerrors == 0)
m_log.DebugFormat("[ARCHIVER]: Successfully added all {0} assets", m_foundAssetUuids.Count);
else
m_log.DebugFormat("[ARCHIVER]: Successfully added {0} assets ({1} of total possible assets requested were not found, were damaged or were not assets)",
m_foundAssetUuids.Count, totalerrors);
PerformAssetsRequestCallback(m_timeout);
}
private void OnTimeout(object source, ElapsedEventArgs args)
{
m_timeout = true;
}
/// <summary>
/// Perform the callback on the original requester of the assets
/// </summary>
protected void PerformAssetsRequestCallback(object o)
private void PerformAssetsRequestCallback(object o)
{
if(m_assetsRequestCallback == null)
return;
Culture.SetCurrentCulture();
Boolean timedOut = (Boolean)o;
@@ -331,7 +210,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
}
}
protected AssetBase PostProcess(AssetBase asset)
private AssetBase PostProcess(AssetBase asset)
{
if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home"))
{

View File

@@ -176,6 +176,14 @@ namespace OpenSim.Region.CoreModules.World.Land
}
}
public void SendParcelsOverlay(IClientAPI client)
{
if (m_landManagementModule != null)
{
m_landManagementModule.SendParcelOverlay(client);
}
}
public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
{
if (m_landManagementModule != null)