Be smarter about stopping timers. Cleanup formatting.
Use a boolean flag to tell timers that fire after IRegionModuleBase.Close() is called that they should not execute. Also, I used MonoDevelop's auto-formatting feature to format the code uniformly. No guarantee about variable names though.bulletsim
parent
34b6904939
commit
a01c44e74d
|
@ -79,13 +79,12 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
|||
TIME,
|
||||
SEQUENTIAL,
|
||||
OVERWRITE
|
||||
};
|
||||
}
|
||||
|
||||
public class AutoBackupModule : ISharedRegionModule, IRegionModuleBase
|
||||
{
|
||||
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static readonly ILog m_log = LogManager.GetLogger (MethodBase.GetCurrentMethod ().DeclaringType);
|
||||
|
||||
//AutoBackupModuleState: Auto-Backup state for one region (scene).
|
||||
public class AutoBackupModuleState
|
||||
|
@ -173,8 +172,11 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
|||
readonly Dictionary<double, Timer> timers = new Dictionary<double, Timer> (1);
|
||||
readonly Dictionary<Timer, List<IScene>> timerMap = new Dictionary<Timer, List<IScene>> (1);
|
||||
private IConfigSource m_configSource = null;
|
||||
private bool m_Enabled = false; //Whether the shared module should be enabled at all. NOT the same as m_Enabled in AutoBackupModuleState!
|
||||
|
||||
private bool m_Enabled = false;
|
||||
//Whether the shared module should be enabled at all. NOT the same as m_Enabled in AutoBackupModuleState!
|
||||
private bool m_closed = false;
|
||||
//True means IRegionModuleBase.Close() was called on us, and we should stop operation ASAP.
|
||||
//Used to prevent elapsing timers after Close() is called from trying to start an autobackup while the sim is shutting down.
|
||||
public AutoBackupModule ()
|
||||
{
|
||||
|
||||
|
@ -186,11 +188,9 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
|||
//Determine if we have been enabled at all in OpenSim.ini -- this is part and parcel of being an optional module
|
||||
m_configSource = source;
|
||||
IConfig moduleConfig = source.Configs["Modules"];
|
||||
if (moduleConfig != null)
|
||||
{
|
||||
if (moduleConfig != null) {
|
||||
m_Enabled = moduleConfig.GetBoolean ("AutoBackupModule", false);
|
||||
if (m_Enabled)
|
||||
{
|
||||
if (m_Enabled) {
|
||||
m_log.Info ("[AUTO BACKUP MODULE]: AutoBackupModule enabled");
|
||||
}
|
||||
}
|
||||
|
@ -219,8 +219,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
|||
Timer timer = abms.GetTimer ();
|
||||
List<IScene> list = timerMap[timer];
|
||||
list.Remove (scene);
|
||||
if(list.Count == 0)
|
||||
{
|
||||
if (list.Count == 0) {
|
||||
timerMap.Remove (timer);
|
||||
timers.Remove (timer.Interval);
|
||||
timer.Close ();
|
||||
|
@ -242,41 +241,35 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
|||
|
||||
//Read the config settings and set variables.
|
||||
IConfig config = m_configSource.Configs["AutoBackupModule"];
|
||||
if(config == null)
|
||||
{
|
||||
if (config == null) {
|
||||
//No config settings for any regions, let's just give up.
|
||||
st.SetEnabled (false);
|
||||
m_log.Info ("[AUTO BACKUP MODULE]: Region " + sRegionName + " is NOT AutoBackup enabled.");
|
||||
return;
|
||||
}
|
||||
st.SetEnabled (config.GetBoolean (sRegionName + ".AutoBackup", false));
|
||||
if(!st.GetEnabled()) //If you don't want AutoBackup, we stop.
|
||||
{
|
||||
//If you don't want AutoBackup, we stop.
|
||||
if (!st.GetEnabled ()) {
|
||||
m_log.Info ("[AUTO BACKUP MODULE]: Region " + sRegionName + " is NOT AutoBackup enabled.");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
m_log.Info ("[AUTO BACKUP MODULE]: Region " + sRegionName + " is AutoBackup ENABLED.");
|
||||
}
|
||||
|
||||
//Borrow an existing timer if one exists for the same interval; otherwise, make a new one.
|
||||
double interval = config.GetDouble (sRegionName + ".AutoBackupInterval", 720) * 60000;
|
||||
if(timers.ContainsKey(interval))
|
||||
{
|
||||
if (timers.ContainsKey (interval)) {
|
||||
st.SetTimer (timers[interval]);
|
||||
m_log.Debug ("[AUTO BACKUP MODULE]: Reusing timer for " + interval + " msec for region " + sRegionName);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
//0 or negative interval == do nothing.
|
||||
if(interval <= 0.0)
|
||||
{
|
||||
if (interval <= 0.0) {
|
||||
st.SetEnabled (false);
|
||||
return;
|
||||
}
|
||||
Timer tim = new Timer (interval);
|
||||
st.SetTimer(tim); //Milliseconds -> minutes
|
||||
st.SetTimer (tim);
|
||||
//Milliseconds -> minutes
|
||||
timers.Add (interval, tim);
|
||||
tim.Elapsed += HandleElapsed;
|
||||
tim.AutoReset = true;
|
||||
|
@ -285,12 +278,9 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
|||
}
|
||||
|
||||
//Add the current region to the list of regions tied to this timer.
|
||||
if(timerMap.ContainsKey(st.GetTimer()))
|
||||
{
|
||||
if (timerMap.ContainsKey (st.GetTimer ())) {
|
||||
timerMap[st.GetTimer ()].Add (scene);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
List<IScene> scns = new List<IScene> (1);
|
||||
scns.Add (scene);
|
||||
timerMap.Add (st.GetTimer (), scns);
|
||||
|
@ -300,20 +290,13 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
|||
|
||||
//Set file naming algorithm
|
||||
string namingtype = config.GetString (sRegionName + ".AutoBackupNaming", "Time");
|
||||
if(namingtype.Equals("Time", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
if (namingtype.Equals ("Time", StringComparison.CurrentCultureIgnoreCase)) {
|
||||
st.SetNamingType (NamingType.TIME);
|
||||
}
|
||||
else if(namingtype.Equals("Sequential", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
} else if (namingtype.Equals ("Sequential", StringComparison.CurrentCultureIgnoreCase)) {
|
||||
st.SetNamingType (NamingType.SEQUENTIAL);
|
||||
}
|
||||
else if(namingtype.Equals("Overwrite", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
} else if (namingtype.Equals ("Overwrite", StringComparison.CurrentCultureIgnoreCase)) {
|
||||
st.SetNamingType (NamingType.OVERWRITE);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
m_log.Warn ("Unknown naming type specified for region " + scene.RegionInfo.RegionName + ": " + namingtype);
|
||||
st.SetNamingType (NamingType.TIME);
|
||||
}
|
||||
|
@ -322,51 +305,39 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
|||
st.SetBackupDir (config.GetString (sRegionName + ".AutoBackupDir", "."));
|
||||
|
||||
//Let's give the user *one* convenience and auto-mkdir
|
||||
if(st.GetBackupDir() != ".")
|
||||
{
|
||||
try
|
||||
{
|
||||
if (st.GetBackupDir () != ".") {
|
||||
try {
|
||||
DirectoryInfo dirinfo = new DirectoryInfo (st.GetBackupDir ());
|
||||
if(!dirinfo.Exists)
|
||||
{
|
||||
if (!dirinfo.Exists) {
|
||||
dirinfo.Create ();
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
m_log.Warn("BAD NEWS. You won't be able to save backups to directory " + st.GetBackupDir() +
|
||||
" because it doesn't exist or there's a permissions issue with it. Here's the exception.", e);
|
||||
} catch (Exception e) {
|
||||
m_log.Warn ("BAD NEWS. You won't be able to save backups to directory " + st.GetBackupDir () + " because it doesn't exist or there's a permissions issue with it. Here's the exception.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleElapsed (object sender, ElapsedEventArgs e)
|
||||
{
|
||||
if (m_closed)
|
||||
return;
|
||||
bool heuristicsRun = false;
|
||||
bool heuristicsPassed = false;
|
||||
if(!timerMap.ContainsKey((Timer) sender))
|
||||
{
|
||||
if (!timerMap.ContainsKey ((Timer)sender)) {
|
||||
m_log.Debug ("Code-up error: timerMap doesn't contain timer " + sender.ToString ());
|
||||
}
|
||||
foreach(IScene scene in timerMap[(Timer)sender])
|
||||
{
|
||||
foreach (IScene scene in timerMap[(Timer)sender]) {
|
||||
AutoBackupModuleState state = states[scene];
|
||||
bool heuristics = state.GetBusyCheck ();
|
||||
|
||||
//Fast path: heuristics are on; already ran em; and sim is fine; OR, no heuristics for the region.
|
||||
if((heuristics && heuristicsRun && heuristicsPassed)
|
||||
|| !heuristics)
|
||||
{
|
||||
if ((heuristics && heuristicsRun && heuristicsPassed) || !heuristics) {
|
||||
doRegionBackup (scene);
|
||||
}
|
||||
//Heuristics are on; ran but we're too busy -- keep going. Maybe another region will have heuristics off!
|
||||
else if(heuristics && heuristicsRun && !heuristicsPassed)
|
||||
{
|
||||
} else if (heuristics && heuristicsRun && !heuristicsPassed) {
|
||||
continue;
|
||||
}
|
||||
//Logical Deduction: heuristics are on but haven't been run
|
||||
else
|
||||
{
|
||||
} else {
|
||||
heuristicsPassed = RunHeuristics ();
|
||||
heuristicsRun = true;
|
||||
if (!heuristicsPassed)
|
||||
|
@ -382,8 +353,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
|||
IRegionArchiverModule iram = scene.RequestModuleInterface<IRegionArchiverModule> ();
|
||||
string savePath = BuildOarPath (scene.RegionInfo.RegionName, state.GetBackupDir (), state.GetNamingType ());
|
||||
//m_log.Debug("[AUTO BACKUP MODULE]: savePath = " + savePath);
|
||||
if(savePath == null)
|
||||
{
|
||||
if (savePath == null) {
|
||||
m_log.Warn ("[AUTO BACKUP MODULE]: savePath is null in HandleElapsed");
|
||||
return;
|
||||
}
|
||||
|
@ -392,15 +362,11 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
|||
}
|
||||
|
||||
string IRegionModuleBase.Name {
|
||||
get {
|
||||
return "AutoBackupModule";
|
||||
}
|
||||
get { return "AutoBackupModule"; }
|
||||
}
|
||||
|
||||
Type IRegionModuleBase.ReplaceableInterface {
|
||||
get {
|
||||
return null;
|
||||
}
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -413,16 +379,14 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
|||
#endregion
|
||||
|
||||
//Is this even needed?
|
||||
public bool IsSharedModule
|
||||
{
|
||||
public bool IsSharedModule {
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
private string BuildOarPath (string regionName, string baseDir, NamingType naming)
|
||||
{
|
||||
FileInfo path = null;
|
||||
switch(naming)
|
||||
{
|
||||
switch (naming) {
|
||||
case NamingType.OVERWRITE:
|
||||
path = new FileInfo (baseDir + Path.DirectorySeparatorChar + regionName);
|
||||
return path.FullName;
|
||||
|
@ -478,11 +442,10 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
|||
m_dirName = dirName;
|
||||
m_regionName = regionName;
|
||||
long biggestExistingFile = HalfIntervalMaximize (1, FileExistsTest);
|
||||
biggestExistingFile++; //We don't want to overwrite the biggest existing file; we want to write to the NEXT biggest.
|
||||
|
||||
biggestExistingFile++;
|
||||
//We don't want to overwrite the biggest existing file; we want to write to the NEXT biggest.
|
||||
uniqueFile = new FileInfo (m_dirName + Path.DirectorySeparatorChar + m_regionName + "_" + biggestExistingFile + ".oar");
|
||||
if(uniqueFile.Exists)
|
||||
{
|
||||
if (uniqueFile.Exists) {
|
||||
//Congratulations, your strange deletion patterns fooled my half-interval search into picking an existing file!
|
||||
//Now you get to pay the performance cost :)
|
||||
uniqueFile = UniqueFileSearchLinear (biggestExistingFile);
|
||||
|
@ -502,20 +465,16 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
|||
if (scriptName == null || scriptName.Length <= 0)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
FileInfo fi = new FileInfo (scriptName);
|
||||
if(fi.Exists)
|
||||
{
|
||||
if (fi.Exists) {
|
||||
ProcessStartInfo psi = new ProcessStartInfo (scriptName);
|
||||
psi.Arguments = savePath;
|
||||
psi.CreateNoWindow = true;
|
||||
Process proc = Process.Start (psi);
|
||||
proc.ErrorDataReceived += HandleProcErrorDataReceived;
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
} catch (Exception e) {
|
||||
m_log.Warn ("Exception encountered when trying to run script for oar backup " + savePath, e);
|
||||
}
|
||||
}
|
||||
|
@ -527,10 +486,10 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
|||
|
||||
private void StopAllTimers ()
|
||||
{
|
||||
foreach(Timer t in timerMap.Keys)
|
||||
{
|
||||
foreach (Timer t in timerMap.Keys) {
|
||||
t.Close ();
|
||||
}
|
||||
m_closed = true;
|
||||
}
|
||||
|
||||
/* Find the largest value for which the predicate returns true.
|
||||
|
@ -549,33 +508,24 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
|||
if (start < 0)
|
||||
throw new IndexOutOfRangeException ("Start value for HalfIntervalMaximize must be non-negative");
|
||||
|
||||
do
|
||||
{
|
||||
if(pred(curr))
|
||||
{
|
||||
if(curr > biggest)
|
||||
{
|
||||
do {
|
||||
if (pred (curr)) {
|
||||
if (curr > biggest) {
|
||||
biggest = curr;
|
||||
}
|
||||
prev = curr;
|
||||
if(curr == 0)
|
||||
{
|
||||
if (curr == 0) {
|
||||
//Special case because 0 * 2 = 0 :)
|
||||
curr = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
//Look deeper
|
||||
curr *= 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// We went too far, back off halfway
|
||||
curr = (curr + prev) / 2;
|
||||
}
|
||||
}
|
||||
while(curr - prev > 0);
|
||||
} while (curr - prev > 0);
|
||||
|
||||
return biggest;
|
||||
}
|
||||
|
@ -592,11 +542,9 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
|
|||
{
|
||||
long l = start;
|
||||
FileInfo retval = null;
|
||||
do
|
||||
{
|
||||
do {
|
||||
retval = new FileInfo (m_dirName + Path.DirectorySeparatorChar + m_regionName + "_" + (l++) + ".oar");
|
||||
}
|
||||
while(retval.Exists);
|
||||
} while (retval.Exists);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue