From 0995fedcaca9a921488929ee40f68c71fbba7a70 Mon Sep 17 00:00:00 2001 From: Sean McNamara Date: Mon, 2 May 2011 04:32:31 -0400 Subject: AutoBackupModule: Implement per-region settings in Regions.ini. --- .../World/AutoBackup/AutoBackupModule.cs | 291 +++++++++++++-------- 1 file changed, 186 insertions(+), 105 deletions(-) (limited to 'OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs') diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs index 4a9615d..ce9a448 100644 --- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs +++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs @@ -55,7 +55,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// /// AutoBackupModule: save OAR region backups to disk periodically - /// + /// /// /// Config Settings Documentation. /// At the TOP LEVEL, e.g. in OpenSim.ini, we have the following options: @@ -96,7 +96,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// AutoBackupAgentThreshold: int. Default: 10. Upper bound on # of agents in region required for BusyCheck heuristics to pass. /// If the number of agents is greater than this value, don't take a backup right now /// Save memory by setting low initial capacities. Minimizes impact in common cases of all regions using same interval, and instances hosting 1 ~ 4 regions. - /// Also helps if you don't want AutoBackup at all. + /// Also helps if you don't want AutoBackup at all. /// public class AutoBackupModule : ISharedRegionModule { @@ -110,17 +110,18 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup new Dictionary>(1); private readonly Dictionary m_timers = new Dictionary(1); + private delegate T DefaultGetter(string settingName, T defaultValue); private bool m_enabled; - /// - /// Whether the shared module should be enabled at all. NOT the same as m_Enabled in AutoBackupModuleState! + /// + /// Whether the shared module should be enabled at all. NOT the same as m_Enabled in AutoBackupModuleState! /// private bool m_closed; private IConfigSource m_configSource; - /// - /// Required by framework. + /// + /// Required by framework. /// public bool IsSharedModule { @@ -129,25 +130,25 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup #region ISharedRegionModule Members - /// - /// Identifies the module to the system. + /// + /// Identifies the module to the system. /// string IRegionModuleBase.Name { get { return "AutoBackupModule"; } } - /// - /// We don't implement an interface, this is a single-use module. + /// + /// We don't implement an interface, this is a single-use module. /// Type IRegionModuleBase.ReplaceableInterface { get { return null; } } - /// - /// Called once in the lifetime of the module at startup. - /// + /// + /// Called once in the lifetime of the module at startup. + /// /// The input config source for OpenSim.ini. void IRegionModuleBase.Initialise(IConfigSource source) { @@ -184,8 +185,8 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup m_log.Debug(abms.ToString()); } - /// - /// Called once at de-init (sim shutting down). + /// + /// Called once at de-init (sim shutting down). /// void IRegionModuleBase.Close() { @@ -198,17 +199,17 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup this.StopAllTimers(); } - /// - /// Currently a no-op for AutoBackup because we have to wait for region to be fully loaded. - /// + /// + /// Currently a no-op for AutoBackup because we have to wait for region to be fully loaded. + /// /// void IRegionModuleBase.AddRegion(Scene scene) { } - /// - /// Here we just clean up some resources and stop the OAR backup (if any) for the given scene. - /// + /// + /// Here we just clean up some resources and stop the OAR backup (if any) for the given scene. + /// /// The scene (region) to stop performing AutoBackup on. void IRegionModuleBase.RemoveRegion(Scene scene) { @@ -237,10 +238,10 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup } } - /// - /// Most interesting/complex code paths in AutoBackup begin here. - /// We read lots of Nini config, maybe set a timer, add members to state tracking Dictionaries, etc. - /// + /// + /// Most interesting/complex code paths in AutoBackup begin here. + /// We read lots of Nini config, maybe set a timer, add members to state tracking Dictionaries, etc. + /// /// The scene to (possibly) perform AutoBackup on. void IRegionModuleBase.RegionLoaded(Scene scene) { @@ -260,8 +261,8 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup m_log.Debug((abms == null ? "DEFAULT" : abms.ToString())); } - /// - /// Currently a no-op. + /// + /// Currently a no-op. /// void ISharedRegionModule.PostInitialise() { @@ -269,12 +270,12 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup #endregion - /// - /// Set up internal state for a given scene. Fairly complex code. - /// When this method returns, we've started auto-backup timers, put members in Dictionaries, and created a State object for this scene. - /// - /// The scene to look at. - /// Whether this call is intended to figure out what we consider the "default" config (applied to all regions unless overridden by per-region settings). + /// + /// Set up internal state for a given scene. Fairly complex code. + /// When this method returns, we've started auto-backup timers, put members in Dictionaries, and created a State object for this scene. + /// + /// The scene to look at. + /// Whether this call is intended to figure out what we consider the "default" config (applied to all regions unless overridden by per-region settings). /// An AutoBackupModuleState contains most information you should need to know relevant to auto-backup, as applicable to a single region. private AutoBackupModuleState ParseConfig(IScene scene, bool parseDefault) { @@ -299,16 +300,16 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup } // Read the config settings and set variables. + IConfig regionConfig = (scene != null ? scene.Config.Configs[sRegionName] : null); IConfig config = this.m_configSource.Configs["AutoBackupModule"]; if (config == null) { // defaultState would be disabled too if the section doesn't exist. state = this.m_defaultState; - m_log.Info("[AUTO BACKUP]: Region " + sRegionLabel + " is NOT AutoBackup enabled."); return state; } - bool tmpEnabled = config.GetBoolean(prepend + "AutoBackup", this.m_defaultState.Enabled); + bool tmpEnabled = ResolveBoolean("AutoBackup", this.m_defaultState.Enabled, config, regionConfig); if (state == null && tmpEnabled != this.m_defaultState.Enabled) //Varies from default state { @@ -332,8 +333,8 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup // Borrow an existing timer if one exists for the same interval; otherwise, make a new one. double interval = - config.GetDouble(prepend + "AutoBackupInterval", this.m_defaultState.IntervalMinutes)* - 60000.0; + this.ResolveDouble("AutoBackupInterval", this.m_defaultState.IntervalMinutes, + config, regionConfig) * 60000.0; if (state == null && interval != this.m_defaultState.IntervalMinutes*60000.0) { state = new AutoBackupModuleState(); @@ -400,8 +401,8 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup } } - bool tmpBusyCheck = config.GetBoolean(prepend + "AutoBackupBusyCheck", - this.m_defaultState.BusyCheck); + bool tmpBusyCheck = ResolveBoolean("AutoBackupBusyCheck", + this.m_defaultState.BusyCheck, config, regionConfig); if (state == null && tmpBusyCheck != this.m_defaultState.BusyCheck) { state = new AutoBackupModuleState(); @@ -413,8 +414,8 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup } // Set file naming algorithm - string stmpNamingType = config.GetString(prepend + "AutoBackupNaming", - this.m_defaultState.NamingType.ToString()); + string stmpNamingType = ResolveString("AutoBackupNaming", + this.m_defaultState.NamingType.ToString(), config, regionConfig); NamingType tmpNamingType; if (stmpNamingType.Equals("Time", StringComparison.CurrentCultureIgnoreCase)) { @@ -445,8 +446,8 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup state.NamingType = tmpNamingType; } - string tmpScript = config.GetString(prepend + "AutoBackupScript", - this.m_defaultState.Script); + string tmpScript = ResolveString("AutoBackupScript", + this.m_defaultState.Script, config, regionConfig); if (state == null && tmpScript != this.m_defaultState.Script) { state = new AutoBackupModuleState(); @@ -457,7 +458,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup state.Script = tmpScript; } - string tmpBackupDir = config.GetString(prepend + "AutoBackupDir", "."); + string tmpBackupDir = ResolveString("AutoBackupDir", ".", config, regionConfig); if (state == null && tmpBackupDir != this.m_defaultState.BackupDir) { state = new AutoBackupModuleState(); @@ -491,10 +492,90 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup return state; } - /// - /// Called when any auto-backup timer expires. This starts the code path for actually performing a backup. - /// - /// + /// + /// Helper function for ParseConfig. + /// + /// + /// + /// + /// + /// + private bool ResolveBoolean(string settingName, bool defaultValue, IConfig global, IConfig local) + { + if(local != null) + { + return local.GetBoolean(settingName, global.GetBoolean(settingName, defaultValue)); + } + else + { + return global.GetBoolean(settingName, defaultValue); + } + } + + /// + /// Helper function for ParseConfig. + /// + /// + /// + /// + /// + /// + private double ResolveDouble(string settingName, double defaultValue, IConfig global, IConfig local) + { + if (local != null) + { + return local.GetDouble(settingName, global.GetDouble(settingName, defaultValue)); + } + else + { + return global.GetDouble(settingName, defaultValue); + } + } + + /// + /// Helper function for ParseConfig. + /// + /// + /// + /// + /// + /// + private int ResolveInt(string settingName, int defaultValue, IConfig global, IConfig local) + { + if (local != null) + { + return local.GetInt(settingName, global.GetInt(settingName, defaultValue)); + } + else + { + return global.GetInt(settingName, defaultValue); + } + } + + /// + /// Helper function for ParseConfig. + /// + /// + /// + /// + /// + /// + private string ResolveString(string settingName, string defaultValue, IConfig global, IConfig local) + { + if (local != null) + { + return local.GetString(settingName, global.GetString(settingName, defaultValue)); + } + else + { + return global.GetString(settingName, defaultValue); + } + } + + /// + /// Called when any auto-backup timer expires. This starts the code path for actually performing a backup. + /// + /// /// private void HandleElapsed(object sender, ElapsedEventArgs e) { @@ -554,9 +635,9 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup } } - /// - /// Save an OAR, register for the callback for when it's done, then call the AutoBackupScript (if applicable). - /// + /// + /// Save an OAR, register for the callback for when it's done, then call the AutoBackupScript (if applicable). + /// /// private void DoRegionBackup(IScene scene) { @@ -585,25 +666,25 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup iram.ArchiveRegion(savePath, guid, null); } - /// - /// Called by the Event Manager when the OnOarFileSaved event is fired. - /// - /// + /// + /// Called by the Event Manager when the OnOarFileSaved event is fired. + /// + /// /// void EventManager_OnOarFileSaved(Guid guid, string message) - { - // Ignore if the OAR save is being done by some other part of the system - if (m_pendingSaves.ContainsKey(guid)) - { - AutoBackupModuleState abms = m_states[(m_pendingSaves[guid])]; - ExecuteScript(abms.Script, abms.LiveRequests[guid]); - m_pendingSaves.Remove(guid); - abms.LiveRequests.Remove(guid); - } + { + // Ignore if the OAR save is being done by some other part of the system + if (m_pendingSaves.ContainsKey(guid)) + { + AutoBackupModuleState abms = m_states[(m_pendingSaves[guid])]; + ExecuteScript(abms.Script, abms.LiveRequests[guid]); + m_pendingSaves.Remove(guid); + abms.LiveRequests.Remove(guid); + } } /// This format may turn out to be too unwieldy to keep... - /// Besides, that's what ctimes are for. But then how do I name each file uniquely without using a GUID? + /// Besides, that's what ctimes are for. But then how do I name each file uniquely without using a GUID? /// Sequential numbers, right? We support those, too! private static string GetTimeString() { @@ -642,12 +723,12 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup } } - /// - /// If the time dilation right at this instant is less than the threshold specified in AutoBackupDilationThreshold (default 0.5), - /// then we return false and trip the busy heuristic's "too busy" path (i.e. don't save an OAR). - /// AutoBackupDilationThreshold is a _LOWER BOUND_. Lower Time Dilation is bad, so if you go lower than our threshold, it's "too busy". - /// - /// + /// + /// If the time dilation right at this instant is less than the threshold specified in AutoBackupDilationThreshold (default 0.5), + /// then we return false and trip the busy heuristic's "too busy" path (i.e. don't save an OAR). + /// AutoBackupDilationThreshold is a _LOWER BOUND_. Lower Time Dilation is bad, so if you go lower than our threshold, it's "too busy". + /// + /// /// Returns true if we're not too busy; false means we've got worse time dilation than the threshold. private bool RunTimeDilationHeuristic(IScene region) { @@ -657,12 +738,12 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup regionName + ".AutoBackupDilationThreshold", 0.5f); } - /// - /// If the root agent count right at this instant is less than the threshold specified in AutoBackupAgentThreshold (default 10), - /// then we return false and trip the busy heuristic's "too busy" path (i.e., don't save an OAR). - /// AutoBackupAgentThreshold is an _UPPER BOUND_. Higher Agent Count is bad, so if you go higher than our threshold, it's "too busy". - /// - /// + /// + /// If the root agent count right at this instant is less than the threshold specified in AutoBackupAgentThreshold (default 10), + /// then we return false and trip the busy heuristic's "too busy" path (i.e., don't save an OAR). + /// AutoBackupAgentThreshold is an _UPPER BOUND_. Higher Agent Count is bad, so if you go higher than our threshold, it's "too busy". + /// + /// /// Returns true if we're not too busy; false means we've got more agents on the sim than the threshold. private bool RunAgentLimitHeuristic(IScene region) { @@ -685,12 +766,12 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup } } - /// - /// Run the script or executable specified by the "AutoBackupScript" config setting. - /// Of course this is a security risk if you let anyone modify OpenSim.ini and they want to run some nasty bash script. - /// But there are plenty of other nasty things that can be done with an untrusted OpenSim.ini, such as running high threat level scripting functions. - /// - /// + /// + /// Run the script or executable specified by the "AutoBackupScript" config setting. + /// Of course this is a security risk if you let anyone modify OpenSim.ini and they want to run some nasty bash script. + /// But there are plenty of other nasty things that can be done with an untrusted OpenSim.ini, such as running high threat level scripting functions. + /// + /// /// private static void ExecuteScript(string scriptName, string savePath) { @@ -719,10 +800,10 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup } } - /// - /// Called if a running script process writes to stderr. - /// - /// + /// + /// Called if a running script process writes to stderr. + /// + /// /// private static void HandleProcErrorDataReceived(object sender, DataReceivedEventArgs e) { @@ -730,8 +811,8 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup " is yacking on stderr: " + e.Data); } - /// - /// Quickly stop all timers from firing. + /// + /// Quickly stop all timers from firing. /// private void StopAllTimers() { @@ -742,11 +823,11 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup this.m_closed = true; } - /// - /// Determine the next unique filename by number, for "Sequential" AutoBackupNamingType. - /// - /// - /// + /// + /// Determine the next unique filename by number, for "Sequential" AutoBackupNamingType. + /// + /// + /// /// private static string GetNextFile(string dirName, string regionName) { @@ -760,12 +841,12 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup return uniqueFile.FullName; } - /// - /// Top-level method for creating an absolute path to an OAR backup file based on what naming scheme the user wants. - /// - /// Name of the region to save. - /// Absolute or relative path to the directory where the file should reside. - /// The naming scheme for the file name. + /// + /// Top-level method for creating an absolute path to an OAR backup file based on what naming scheme the user wants. + /// + /// Name of the region to save. + /// Absolute or relative path to the directory where the file should reside. + /// The naming scheme for the file name. /// private static string BuildOarPath(string regionName, string baseDir, NamingType naming) { @@ -792,11 +873,11 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup return null; } - /// - /// Helper function for Sequential file naming type (see BuildOarPath and GetNextFile). - /// - /// - /// + /// + /// Helper function for Sequential file naming type (see BuildOarPath and GetNextFile). + /// + /// + /// /// private static long GetNextOarFileNumber(string dirName, string regionName) { -- cgit v1.1