Example #1
0
        /// <summary>
        /// <see cref="TimerCallback"/> to be called every tick. Checks validity of the tick, performs workload and schedues the next tick.
        /// </summary>
        /// <param name="state"></param>
        private static void OnTick(object state)
        {
            Logger.LogTick();
            DateTime now = DateTime.Now;

            // Recalculate next run dates if the last tick was more than 90 seconds ago or if it is in the future.
            // Such clock skew implies manual time change, huge NTP leap, machine awakened from hibernation/suspension or some other potentially unsafe state.
            if (now - _lastTick > _skewLimit || now < _lastTick)
            {
                Logger.LogTickSkew();
                foreach (Task task in Config.Tasks.Values)
                {
                    task.RefreshNextRunDate();
                }
                LogCleaner.Start();
                LogCleaner.RefreshNextRunDate();
            }
            else
            {
                DoTick(now);
            }
            // The next tick time has to be readjusted often to maintain the precision of the scheduled tasks.
            // System.Threading.Timer is ridiculously imprecise. The best case scenario skews the timer by 1 ms per minute (1 minute per ~100 days).
            // An alternative would be to create a custom timer implementaion based on high-precision multimedia timers, but
            // System.Threading.Timer is simple to use and guaranteed to be supported pretty much everywhere, so it's good enough.
            SetNextTick(now);
        }
Example #2
0
 /// <summary>
 /// Logs the values and tasks present in <see cref="Config"/>.
 /// </summary>
 public static void LogConfig()
 {
     if (Writer != null)
     {
         Log(string.Format("[Config] Got log retention period {0} days", Config.LogRetention));
         LogCleaner.RefreshNextRunDate(); // Produces log cleaner log line
         foreach (Task task in Config.Tasks.Values)
         {
             task.RefreshNextRunDate(); // Produces task detail log line
         }
     }
 }
Example #3
0
 /// <summary>
 /// <see cref="ServiceBase.Run"/> handler. Opens <see cref="Logger"/> (if configured), loads <see cref="Config"/> and starts the <see cref="Timer"/>.
 /// </summary>
 /// <param name="args">Command line arguments.</param>
 protected override void OnStart(string[] args)
 {
     if (args.Length == 1 && args[0] == "/log")
     {
         Logger.Open(Path.Combine(Config.LogRoot, "service.log"));
     }
     Logger.LogServiceStarted();
     Config.Load();
     LogCleaner.Start();
     IpcServer.Start();
     SetNextTick(DateTime.Now);
 }
Example #4
0
 /// <summary>
 /// Performs workload during normal tick. Runs <see cref="Task"/> or <see cref="LogCleaner"/> if they are scheduled to be run in the current tick.
 /// </summary>
 /// <param name="now"></param>
 private static void DoTick(DateTime now)
 {
     foreach (Task task in Config.Tasks.Values)
     {
         if (task.NextRunDate <= now)
         {
             task.Start();
             task.RefreshNextRunDate();
         }
     }
     if (LogCleaner.NextRunDate <= now)
     {
         LogCleaner.Start();
         LogCleaner.RefreshNextRunDate();
     }
 }
Example #5
0
 /// <summary>
 /// Reloads service configuration.
 /// </summary>
 public void ReloadConfig()
 {
     Logger.LogIpcReloadMessage();
     Config.Load();
     LogCleaner.Start();
 }