aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
diff options
context:
space:
mode:
authorSean McNamara2011-04-11 12:34:26 -0400
committerSean McNamara2011-04-11 12:34:26 -0400
commit4974a1ce69fb3a1d2937c7de7ba93079a918eb3a (patch)
treedd7bec46433f486f8a55ae2b5eaef280940b4083 /OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
parentMerge git://opensimulator.org/git/opensim (diff)
downloadopensim-SC-4974a1ce69fb3a1d2937c7de7ba93079a918eb3a.zip
opensim-SC-4974a1ce69fb3a1d2937c7de7ba93079a918eb3a.tar.gz
opensim-SC-4974a1ce69fb3a1d2937c7de7ba93079a918eb3a.tar.bz2
opensim-SC-4974a1ce69fb3a1d2937c7de7ba93079a918eb3a.tar.xz
AutoBackup: Support region-independent settings too.
Diffstat (limited to 'OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs')
-rw-r--r--OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs232
1 files changed, 175 insertions, 57 deletions
diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
index 7660342..37a2d97 100644
--- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
+++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
@@ -49,6 +49,8 @@ using OpenSim.Region.Framework.Scenes;
49 * VERY IMPORTANT: You must create the key name as follows: <Region Name>.<Key Name> 49 * VERY IMPORTANT: You must create the key name as follows: <Region Name>.<Key Name>
50 * Example: My region is named Foo. 50 * Example: My region is named Foo.
51 * If I wanted to specify the "AutoBackupInterval" key below, I would name my key "Foo.AutoBackupInterval", under the [AutoBackupModule] section of OpenSim.ini. 51 * If I wanted to specify the "AutoBackupInterval" key below, I would name my key "Foo.AutoBackupInterval", under the [AutoBackupModule] section of OpenSim.ini.
52 * Instead of specifying them on a per-region basis, you can also omit the region name to specify the default setting for all regions.
53 * Region-specific settings take precedence.
52 * AutoBackup: True/False. Default: False. If True, activate auto backup functionality. 54 * AutoBackup: True/False. Default: False. If True, activate auto backup functionality.
53 * This is the only required option for enabling auto-backup; the other options have sane defaults. 55 * This is the only required option for enabling auto-backup; the other options have sane defaults.
54 * If False, the auto-backup module becomes a no-op for the region, and all other AutoBackup* settings are ignored. 56 * If False, the auto-backup module becomes a no-op for the region, and all other AutoBackup* settings are ignored.
@@ -121,6 +123,18 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
121 { 123 {
122 return m_timer; 124 return m_timer;
123 } 125 }
126
127 public double GetIntervalMinutes ()
128 {
129 if(m_timer == null)
130 {
131 return -1.0;
132 }
133 else
134 {
135 return m_timer.Interval / 60000.0;
136 }
137 }
124 138
125 public void SetTimer (Timer t) 139 public void SetTimer (Timer t)
126 { 140 {
@@ -167,6 +181,19 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
167 { 181 {
168 m_naming = n; 182 m_naming = n;
169 } 183 }
184
185 public string ToString()
186 {
187 string retval = "";
188
189 retval += "[AUTO BACKUP]: AutoBackup: " + (GetEnabled() ? "ENABLED" : "DISABLED") + "\n";
190 retval += "[AUTO BACKUP]: Interval: " + GetIntervalMinutes() + " minutes" + "\n";
191 retval += "[AUTO BACKUP]: Do Busy Check: " + (GetBusyCheck() ? "Yes" : "No") + "\n";
192 retval += "[AUTO BACKUP]: Naming Type: " + GetNamingType().ToString() + "\n";
193 retval += "[AUTO BACKUP]: Backup Dir: " + GetBackupDir() + "\n";
194 retval += "[AUTO BACKUP]: Script: " + GetScript() + "\n";
195 return retval;
196 }
170 } 197 }
171 198
172 //Save memory by setting low initial capacities. Minimizes impact in common cases of all regions using same interval, and instances hosting 1 ~ 4 regions. 199 //Save memory by setting low initial capacities. Minimizes impact in common cases of all regions using same interval, and instances hosting 1 ~ 4 regions.
@@ -180,6 +207,8 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
180 private bool m_closed = false; 207 private bool m_closed = false;
181 //True means IRegionModuleBase.Close() was called on us, and we should stop operation ASAP. 208 //True means IRegionModuleBase.Close() was called on us, and we should stop operation ASAP.
182 //Used to prevent elapsing timers after Close() is called from trying to start an autobackup while the sim is shutting down. 209 //Used to prevent elapsing timers after Close() is called from trying to start an autobackup while the sim is shutting down.
210 readonly AutoBackupModuleState defaultState = new AutoBackupModuleState();
211
183 public AutoBackupModule () 212 public AutoBackupModule ()
184 { 213 {
185 214
@@ -194,9 +223,20 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
194 if (moduleConfig != null) { 223 if (moduleConfig != null) {
195 m_Enabled = moduleConfig.GetBoolean ("AutoBackupModule", false); 224 m_Enabled = moduleConfig.GetBoolean ("AutoBackupModule", false);
196 if (m_Enabled) { 225 if (m_Enabled) {
197 m_log.Info ("[AUTO BACKUP MODULE]: AutoBackupModule enabled"); 226 m_log.Info ("[AUTO BACKUP]: AutoBackupModule enabled");
198 } 227 }
199 } 228 }
229
230 Timer defTimer = new Timer(720 * 60000);
231 defaultState.SetTimer(defTimer);
232 timers.Add (720*60000, defTimer);
233 defTimer.Elapsed += HandleElapsed;
234 defTimer.AutoReset = true;
235 defTimer.Start ();
236
237 AutoBackupModuleState abms = ParseConfig(null, false);
238 m_log.Debug("[AUTO BACKUP]: Config for default");
239 m_log.Debug(abms.ToString());
200 } 240 }
201 241
202 void IRegionModuleBase.Close () 242 void IRegionModuleBase.Close ()
@@ -238,87 +278,162 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
238 //This really ought not to happen, but just in case, let's pretend it didn't... 278 //This really ought not to happen, but just in case, let's pretend it didn't...
239 if (scene == null) 279 if (scene == null)
240 return; 280 return;
241 281
242 string sRegionName = scene.RegionInfo.RegionName; 282 AutoBackupModuleState abms = ParseConfig(scene, true);
243 AutoBackupModuleState st = new AutoBackupModuleState (); 283 m_log.Debug("[AUTO BACKUP]: Config for " + scene.RegionInfo.RegionName);
244 states.Add (scene, st); 284 m_log.Debug(abms.ToString());
245 285 }
246 //Read the config settings and set variables. 286
287 AutoBackupModuleState ParseConfig (IScene scene, bool parseDefault)
288 {
289 string sRegionName;
290 string sRegionLabel;
291 string prepend;
292 AutoBackupModuleState state;
293
294 if(parseDefault)
295 {
296 sRegionName = null;
297 sRegionLabel = "DEFAULT";
298 prepend = "";
299 state = defaultState;
300 }
301 else
302 {
303 sRegionName = scene.RegionInfo.RegionName;
304 sRegionLabel = sRegionName;
305 prepend = sRegionName + ".";
306 state = null;
307 }
308
309 //Read the config settings and set variables.
247 IConfig config = m_configSource.Configs["AutoBackupModule"]; 310 IConfig config = m_configSource.Configs["AutoBackupModule"];
248 if (config == null) { 311 if (config == null) {
249 //No config settings for any regions, let's just give up. 312 state = defaultState; //defaultState would be disabled too if the section doesn't exist.
250 st.SetEnabled (false); 313 m_log.Info ("[AUTO BACKUP]: Region " + sRegionLabel + " is NOT AutoBackup enabled.");
251 m_log.Info ("[AUTO BACKUP MODULE]: Region " + sRegionName + " is NOT AutoBackup enabled."); 314 return state;
252 return; 315 }
316
317 bool tmpEnabled = config.GetBoolean (prepend + "AutoBackup", defaultState.GetEnabled());
318 if(state == null && tmpEnabled != defaultState.GetEnabled()) //Varies from default state
319 {
320 state = new AutoBackupModuleState();
321 state.SetEnabled (tmpEnabled);
253 } 322 }
254 st.SetEnabled (config.GetBoolean (sRegionName + ".AutoBackup", false)); 323
255 //If you don't want AutoBackup, we stop. 324 //If you don't want AutoBackup, we stop.
256 if (!st.GetEnabled ()) { 325 if ((state == null && !defaultState.GetEnabled()) || !state.GetEnabled ()) {
257 m_log.Info ("[AUTO BACKUP MODULE]: Region " + sRegionName + " is NOT AutoBackup enabled."); 326 m_log.Info ("[AUTO BACKUP]: Region " + sRegionLabel + " is NOT AutoBackup enabled.");
258 return; 327 return state;
259 } else { 328 } else {
260 m_log.Info ("[AUTO BACKUP MODULE]: Region " + sRegionName + " is AutoBackup ENABLED."); 329 m_log.Info ("[AUTO BACKUP]: Region " + sRegionLabel + " is AutoBackup ENABLED.");
261 } 330 }
262 331
263 //Borrow an existing timer if one exists for the same interval; otherwise, make a new one. 332 //Borrow an existing timer if one exists for the same interval; otherwise, make a new one.
264 double interval = config.GetDouble (sRegionName + ".AutoBackupInterval", 720) * 60000; 333 double interval = config.GetDouble (prepend + "AutoBackupInterval", defaultState.GetIntervalMinutes()) * 60000.0;
334 if(state == null && interval != defaultState.GetIntervalMinutes() * 60000.0)
335 {
336 state = new AutoBackupModuleState();
337 }
338
265 if (timers.ContainsKey (interval)) { 339 if (timers.ContainsKey (interval)) {
266 st.SetTimer (timers[interval]); 340 if(state != null)
267 m_log.Debug ("[AUTO BACKUP MODULE]: Reusing timer for " + interval + " msec for region " + sRegionName); 341 state.SetTimer (timers[interval]);
342 m_log.Debug ("[AUTO BACKUP]: Reusing timer for " + interval + " msec for region " + sRegionLabel);
268 } else { 343 } else {
269 //0 or negative interval == do nothing. 344 //0 or negative interval == do nothing.
270 if (interval <= 0.0) { 345 if (interval <= 0.0 && state != null) {
271 st.SetEnabled (false); 346 state.SetEnabled (false);
272 return; 347 return state;
273 } 348 }
274 Timer tim = new Timer (interval); 349 Timer tim = new Timer (interval);
275 st.SetTimer (tim); 350 state.SetTimer (tim);
276 //Milliseconds -> minutes 351 //Milliseconds -> minutes
277 timers.Add (interval, tim); 352 timers.Add (interval, tim);
278 tim.Elapsed += HandleElapsed; 353 tim.Elapsed += HandleElapsed;
279 tim.AutoReset = true; 354 tim.AutoReset = true;
280 tim.Start (); 355 tim.Start ();
281 //m_log.Debug("[AUTO BACKUP MODULE]: New timer for " + interval + " msec for region " + sRegionName); 356 //m_log.Debug("[AUTO BACKUP]: New timer for " + interval + " msec for region " + sRegionName);
282 } 357 }
283 358
284 //Add the current region to the list of regions tied to this timer. 359 //Add the current region to the list of regions tied to this timer.
285 if (timerMap.ContainsKey (st.GetTimer ())) { 360 if (timerMap.ContainsKey (state.GetTimer ())) {
286 timerMap[st.GetTimer ()].Add (scene); 361 timerMap[state.GetTimer ()].Add (scene);
287 } else { 362 } else {
288 List<IScene> scns = new List<IScene> (1); 363 List<IScene> scns = new List<IScene> (1);
289 scns.Add (scene); 364 scns.Add (scene);
290 timerMap.Add (st.GetTimer (), scns); 365 timerMap.Add (state.GetTimer (), scns);
366 }
367
368 bool tmpBusyCheck = config.GetBoolean (prepend + "AutoBackupBusyCheck", defaultState.GetBusyCheck());
369 if(state == null && tmpBusyCheck != defaultState.GetBusyCheck())
370 {
371 state = new AutoBackupModuleState();
291 } 372 }
292 373
293 st.SetBusyCheck (config.GetBoolean (sRegionName + ".AutoBackupBusyCheck", true)); 374 if(state != null)
375 {
376 state.SetBusyCheck (tmpBusyCheck);
377 }
294 378
295 //Set file naming algorithm 379 //Set file naming algorithm
296 string namingtype = config.GetString (sRegionName + ".AutoBackupNaming", "Time"); 380 string stmpNamingType = config.GetString (prepend + "AutoBackupNaming", defaultState.GetNamingType().ToString());
297 if (namingtype.Equals ("Time", StringComparison.CurrentCultureIgnoreCase)) { 381 NamingType tmpNamingType;
298 st.SetNamingType (NamingType.TIME); 382 if (stmpNamingType.Equals ("Time", StringComparison.CurrentCultureIgnoreCase)) {
299 } else if (namingtype.Equals ("Sequential", StringComparison.CurrentCultureIgnoreCase)) { 383 tmpNamingType = NamingType.TIME;
300 st.SetNamingType (NamingType.SEQUENTIAL); 384 } else if (stmpNamingType.Equals ("Sequential", StringComparison.CurrentCultureIgnoreCase)) {
301 } else if (namingtype.Equals ("Overwrite", StringComparison.CurrentCultureIgnoreCase)) { 385 tmpNamingType = NamingType.SEQUENTIAL;
302 st.SetNamingType (NamingType.OVERWRITE); 386 } else if (stmpNamingType.Equals ("Overwrite", StringComparison.CurrentCultureIgnoreCase)) {
387 tmpNamingType = NamingType.OVERWRITE;
303 } else { 388 } else {
304 m_log.Warn ("Unknown naming type specified for region " + scene.RegionInfo.RegionName + ": " + namingtype); 389 m_log.Warn ("Unknown naming type specified for region " + sRegionLabel + ": " + stmpNamingType);
305 st.SetNamingType (NamingType.TIME); 390 tmpNamingType = NamingType.TIME;
306 } 391 }
307 392
308 st.SetScript (config.GetString (sRegionName + ".AutoBackupScript", null)); 393 if(state == null && tmpNamingType != defaultState.GetNamingType())
309 st.SetBackupDir (config.GetString (sRegionName + ".AutoBackupDir", ".")); 394 {
395 state = new AutoBackupModuleState();
396 }
310 397
311 //Let's give the user *one* convenience and auto-mkdir 398 if(state != null)
312 if (st.GetBackupDir () != ".") { 399 {
313 try { 400 state.SetNamingType(tmpNamingType);
314 DirectoryInfo dirinfo = new DirectoryInfo (st.GetBackupDir ());
315 if (!dirinfo.Exists) {
316 dirinfo.Create ();
317 }
318 } catch (Exception e) {
319 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);
320 }
321 } 401 }
402
403 string tmpScript = config.GetString (prepend + "AutoBackupScript", defaultState.GetScript());
404 if(state == null && tmpScript != defaultState.GetScript())
405 {
406 state = new AutoBackupModuleState();
407 }
408
409 if(state != null)
410 {
411 state.SetScript (tmpScript);
412 }
413
414 string tmpBackupDir = config.GetString (prepend + "AutoBackupDir", ".");
415 if(state == null && tmpBackupDir != defaultState.GetBackupDir())
416 {
417 state = new AutoBackupModuleState();
418 }
419
420 if(state != null)
421 {
422 state.SetBackupDir (tmpBackupDir);
423 //Let's give the user *one* convenience and auto-mkdir
424 if (state.GetBackupDir () != ".") {
425 try {
426 DirectoryInfo dirinfo = new DirectoryInfo (state.GetBackupDir ());
427 if (!dirinfo.Exists) {
428 dirinfo.Create ();
429 }
430 } catch (Exception e) {
431 m_log.Warn ("BAD NEWS. You won't be able to save backups to directory " + state.GetBackupDir () + " because it doesn't exist or there's a permissions issue with it. Here's the exception.", e);
432 }
433 }
434 }
435
436 return state;
322 } 437 }
323 438
324 void HandleElapsed (object sender, ElapsedEventArgs e) 439 void HandleElapsed (object sender, ElapsedEventArgs e)
@@ -336,7 +451,10 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
336 if (!timerMap.ContainsKey ((Timer)sender)) { 451 if (!timerMap.ContainsKey ((Timer)sender)) {
337 m_log.Debug ("Code-up error: timerMap doesn't contain timer " + sender.ToString ()); 452 m_log.Debug ("Code-up error: timerMap doesn't contain timer " + sender.ToString ());
338 } 453 }
339 foreach (IScene scene in timerMap[(Timer)sender]) { 454
455 List<IScene> tmap = timerMap[(Timer)sender];
456 if(tmap != null && tmap.Count > 0)
457 foreach (IScene scene in tmap) {
340 AutoBackupModuleState state = states[scene]; 458 AutoBackupModuleState state = states[scene];
341 bool heuristics = state.GetBusyCheck (); 459 bool heuristics = state.GetBusyCheck ();
342 460
@@ -345,14 +463,14 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
345 doRegionBackup (scene); 463 doRegionBackup (scene);
346 //Heuristics are on; ran but we're too busy -- keep going. Maybe another region will have heuristics off! 464 //Heuristics are on; ran but we're too busy -- keep going. Maybe another region will have heuristics off!
347 } else if (heuristics && heuristicsRun && !heuristicsPassed) { 465 } else if (heuristics && heuristicsRun && !heuristicsPassed) {
348 m_log.Info ("[AUTO BACKUP MODULE]: Heuristics: too busy to backup " + scene.RegionInfo.RegionName + " right now."); 466 m_log.Info ("[AUTO BACKUP]: Heuristics: too busy to backup " + scene.RegionInfo.RegionName + " right now.");
349 continue; 467 continue;
350 //Logical Deduction: heuristics are on but haven't been run 468 //Logical Deduction: heuristics are on but haven't been run
351 } else { 469 } else {
352 heuristicsPassed = RunHeuristics (scene); 470 heuristicsPassed = RunHeuristics (scene);
353 heuristicsRun = true; 471 heuristicsRun = true;
354 if (!heuristicsPassed) { 472 if (!heuristicsPassed) {
355 m_log.Info ("[AUTO BACKUP MODULE]: Heuristics: too busy to backup " + scene.RegionInfo.RegionName + " right now."); 473 m_log.Info ("[AUTO BACKUP]: Heuristics: too busy to backup " + scene.RegionInfo.RegionName + " right now.");
356 continue; 474 continue;
357 } 475 }
358 doRegionBackup (scene); 476 doRegionBackup (scene);
@@ -364,16 +482,16 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
364 { 482 {
365 if (scene.RegionStatus != RegionStatus.Up) { 483 if (scene.RegionStatus != RegionStatus.Up) {
366 //We won't backup a region that isn't operating normally. 484 //We won't backup a region that isn't operating normally.
367 m_log.Warn ("[AUTO BACKUP MODULE]: Not backing up region " + scene.RegionInfo.RegionName + " because its status is " + scene.RegionStatus.ToString ()); 485 m_log.Warn ("[AUTO BACKUP]: Not backing up region " + scene.RegionInfo.RegionName + " because its status is " + scene.RegionStatus.ToString ());
368 return; 486 return;
369 } 487 }
370 488
371 AutoBackupModuleState state = states[scene]; 489 AutoBackupModuleState state = states[scene];
372 IRegionArchiverModule iram = scene.RequestModuleInterface<IRegionArchiverModule> (); 490 IRegionArchiverModule iram = scene.RequestModuleInterface<IRegionArchiverModule> ();
373 string savePath = BuildOarPath (scene.RegionInfo.RegionName, state.GetBackupDir (), state.GetNamingType ()); 491 string savePath = BuildOarPath (scene.RegionInfo.RegionName, state.GetBackupDir (), state.GetNamingType ());
374 //m_log.Debug("[AUTO BACKUP MODULE]: savePath = " + savePath); 492 //m_log.Debug("[AUTO BACKUP]: savePath = " + savePath);
375 if (savePath == null) { 493 if (savePath == null) {
376 m_log.Warn ("[AUTO BACKUP MODULE]: savePath is null in HandleElapsed"); 494 m_log.Warn ("[AUTO BACKUP]: savePath is null in HandleElapsed");
377 return; 495 return;
378 } 496 }
379 iram.ArchiveRegion (savePath, null); 497 iram.ArchiveRegion (savePath, null);
@@ -481,7 +599,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
481 try { 599 try {
482 return RunTimeDilationHeuristic (region) && RunAgentLimitHeuristic (region); 600 return RunTimeDilationHeuristic (region) && RunAgentLimitHeuristic (region);
483 } catch (Exception e) { 601 } catch (Exception e) {
484 m_log.Warn ("[AUTO BACKUP MODULE]: Exception in RunHeuristics", e); 602 m_log.Warn ("[AUTO BACKUP]: Exception in RunHeuristics", e);
485 return false; 603 return false;
486 } 604 }
487 } 605 }
@@ -512,7 +630,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
512 //TODO: Why isn't GetRootAgentCount() a method in the IScene interface? Seems generally useful... 630 //TODO: Why isn't GetRootAgentCount() a method in the IScene interface? Seems generally useful...
513 return scene.GetRootAgentCount () <= m_configSource.Configs["AutoBackupModule"].GetInt (regionName + ".AutoBackupAgentThreshold", 10); 631 return scene.GetRootAgentCount () <= m_configSource.Configs["AutoBackupModule"].GetInt (regionName + ".AutoBackupAgentThreshold", 10);
514 } catch (InvalidCastException ice) { 632 } catch (InvalidCastException ice) {
515 m_log.Debug ("[AUTO BACKUP MODULE]: I NEED MAINTENANCE: IScene is not a Scene; can't get root agent count!"); 633 m_log.Debug ("[AUTO BACKUP]: I NEED MAINTENANCE: IScene is not a Scene; can't get root agent count!");
516 return true; 634 return true;
517 //Non-obstructionist safest answer... 635 //Non-obstructionist safest answer...
518 } 636 }