Esempio n. 1
0
        /// <summary>
        /// Bereinigt alle veralteten Protokolleinträge.
        /// </summary>
        internal void CleanupLogEntries()
        {
            // Check time
            if (DateTime.UtcNow < m_nextLogCleanup)
            {
                return;
            }

            // Not again for now
            m_nextLogCleanup = DateTime.UtcNow.AddDays(1);

            // For cleanup
            var firstValid = DateTime.Now.Date.AddDays(-7 * VCRConfiguration.Current.LogLifeTime).ToString(LogEntryDateFormat);

            // Load all jobs
            foreach (var file in LogDirectory.GetFiles("*" + VCRRecordingInfo.FileSuffix))
            {
                if (file.Name.CompareTo(firstValid) < 0)
                {
                    try
                    {
                        // Delete the log entry
                        file.Delete();
                    }
                    catch (Exception e)
                    {
                        // Report error
                        VCRServer.Log(e);
                    }
                }
            }
        }
        /// <summary>
        /// Erzeugt eine neue Verwaltungsinstanz.
        /// </summary>
        /// <param name="server">Die primäre VCR.NET Instanz.</param>
        internal ProfileStateCollection(VCRServer server)
        {
            // Remember
            Server = server;

            // Profiles to use
            var profileNames = VCRProfiles.ProfileNames.ToArray();
            var nameReport   = string.Join(", ", profileNames);

            // Log
            VCRServer.Log(LoggingLevel.Full, Properties.Resources.LoadProfiles, nameReport);

            // Report
            Tools.ExtendedLogging("Loading Profile Collection: {0}", nameReport);

            // Load current profiles
            m_profiles = profileNames.ToDictionary(profileName => profileName, profileName => new ProfileState(this, profileName), ProfileManager.ProfileNameComparer);

            // Now we can create the planner
            m_planner    = RecordingPlanner.Create(this);
            m_planThread = new Thread(PlanThread)
            {
                Name = "Recording Planner", IsBackground = true
            };

            // Configure timer
            m_timer.OnTimerExpired += BeginNewPlan;

            // Start planner
            m_planThread.Start();
        }
Esempio n. 3
0
        /// <summary>
        /// Entfernt veraltete Aufträge aus dem Archiv.
        /// </summary>
        internal void CleanupArchivedJobs()
        {
            // Not yet
            if (DateTime.UtcNow < m_nextArchiveCleanup)
            {
                return;
            }

            // Remember
            m_nextArchiveCleanup = DateTime.UtcNow.AddDays(1);

            // Access limit
            var firstValid   = DateTime.UtcNow.AddDays(-7 * VCRConfiguration.Current.ArchiveLifeTime);
            var jobDirectory = ArchiveDirectory;

            // Protect to avoid parallel operations on the archive directory
            lock (m_Jobs)
                foreach (var file in jobDirectory.GetFiles("*" + VCRJob.FileSuffix))
                {
                    if (file.LastWriteTimeUtc < firstValid)
                    {
                        try
                        {
                            // Delete the log entry
                            file.Delete();
                        }
                        catch (Exception e)
                        {
                            // Report error
                            VCRServer.Log(e);
                        }
                    }
                }
        }
Esempio n. 4
0
 /// <summary>
 /// Startet aller Erweiterung einer bestimmten Art.
 /// </summary>
 /// <param name="extensionType">Die gewünschte Art von Erweiterungen.</param>
 /// <param name="environment">Aller Parameter für die Erweiterungen.</param>
 /// <returns>Die Prozessinformationen zu allen gestarten Erweiterungen.</returns>
 public static void RunSynchronousExtensions(string extensionType, Dictionary <string, string> environment)
 {
     // Forward
     foreach (var process in RunExtensions(GetExtensions(extensionType), environment))
     {
         if (process != null)
         {
             try
             {
                 // Wait on done
                 try
                 {
                     // Do it
                     process.WaitForExit();
                 }
                 finally
                 {
                     // Get rid
                     process.Dispose();
                 }
             }
             catch (Exception e)
             {
                 // Report and catch all!
                 VCRServer.Log(e);
             }
         }
     }
 }
        /// <summary>
        /// Bestätigt den Abschluss einer Operation und die Bereitschaft, die nächste Operation
        /// zu starten.
        /// </summary>
        /// <param name="scheduleIdentifier">Die eindeutige Kennung der Operation.</param>
        /// <param name="isStart">Gesetzt, wenn es sich um einen Startbefehl handelt.</param>
        internal void ConfirmOperation(Guid scheduleIdentifier, bool isStart)
        {
            // Protect and check
            var planner = m_planner;

            if (planner == null)
            {
                return;
            }

            // Make sure that we synchronize with the planning thread
            lock (planner)
                if (m_pendingSchedule == null)
                {
                    // Report
                    VCRServer.Log(LoggingLevel.Errors, "There is no outstanding asynchronous Recording Request for Schedule '{0}'", scheduleIdentifier);
                }
                else if (m_pendingSchedule.Definition.UniqueIdentifier != scheduleIdentifier)
                {
                    // Report
                    VCRServer.Log(LoggingLevel.Errors, "Confirmed asynchronous Recording Request for Schedule '{0}' but waiting for '{1}'", scheduleIdentifier, m_pendingSchedule.Definition.UniqueIdentifier);
                }
                else
                {
                    // Report
                    VCRServer.Log(LoggingLevel.Schedules, "Confirmed asynchronous Recording Request for Schedule '{0}'", scheduleIdentifier);

                    // Check mode
                    if (isStart != m_pendingStart)
                    {
                        VCRServer.Log(LoggingLevel.Errors, "Recording Request confirmed wrong Type of Operation");
                    }

                    // Finish
                    if (m_pendingStart)
                    {
                        planner.Start(m_pendingSchedule);
                    }
                    else
                    {
                        planner.Stop(scheduleIdentifier);
                    }

                    // Reset
                    m_pendingSchedule = null;
                }

            // See what to do next
            BeginNewPlan();
        }
        /// <summary>
        /// Meldet, dass eine Aufzeichnung nun beendet werden kann.
        /// </summary>
        /// <param name="item">Die betroffene Aufzeichnung.</param>
        /// <param name="planner">Die Planungsinstanz.</param>
        void IRecordingPlannerSite.Stop(IScheduleInformation item, RecordingPlanner planner)
        {
            // Report
            VCRServer.Log(LoggingLevel.Schedules, "Done recording '{0}'", item.Definition.Name);

            // Locate the profile - if we don't find it we are in big trouble!
            if (!m_profiles.TryGetValue(item.Resource.Name, out ProfileState profile))
            {
                return;
            }

            // Mark as pending
            m_pendingSchedule = item;
            m_pendingStart    = false;

            // Forward request to profile manager
            m_pendingActions += () => profile.EndRecording(item.Definition.UniqueIdentifier);
        }
Esempio n. 7
0
        /// <summary>
        /// Speichert ein Objekt im XML Format in eine Datei. Fehler werden protokolliert und
        /// nicht als Ausnahmen gemeldet.
        /// </summary>
        /// <param name="instance">Das zu speichernde Objekt.</param>
        /// <param name="path">Der Pfad zur Datei.</param>
        /// <returns>Gesetzt, wenn kein Fehler aufgetreten ist.</returns>
        public static bool SafeSave(object instance, string path)
        {
            // Be safe
            try
            {
                // Write it out
                SerializationTools.Save(instance, path);

                // Did it
                return(true);
            }
            catch (Exception e)
            {
                // Report
                VCRServer.Log(e);

                // Failed
                return(false);
            }
        }
Esempio n. 8
0
 /// <summary>
 /// Aktualisiert einen Zeitwert in der Windows Registrierung.
 /// </summary>
 /// <param name="name">Der Name des Wertes.</param>
 /// <param name="value">Der neue Wert oder <i>null</i>, wenn dieser entfernt
 /// werden soll.</param>
 internal static void SetRegistryTime(string name, DateTime?value)
 {
     // Always be safe
     try
     {
         // Check mode
         if (value.HasValue)
         {
             VCRServer.ServiceRegistry.SetValue(name, value.Value.ToString("u"));
         }
         else
         {
             VCRServer.ServiceRegistry.DeleteValue(name, false);
         }
     }
     catch (Exception e)
     {
         // Report
         VCRServer.Log(e);
     }
 }
Esempio n. 9
0
        /// <summary>
        /// Startet eine einzelne Erweiterung.
        /// </summary>
        /// <param name="extension">Die gewünschte Erweiterung.</param>
        /// <param name="environment">Parameter für die Erweiterung.</param>
        /// <returns>Der gestartete Prozess oder <i>null</i>, wenn ein Start nicht möglich war.</returns>
        public static Process RunExtension(FileInfo extension, Dictionary <string, string> environment)
        {
            // Be safe
            try
            {
                // Create the start record
                var info =
                    new ProcessStartInfo
                {
                    WorkingDirectory = extension.DirectoryName,
                    FileName         = extension.FullName,
                    UseShellExecute  = false,
                    CreateNoWindow   = true,
                    ErrorDialog      = false,
                };

                // Overwrite as wanted
                if (environment != null)
                {
                    foreach (var env in environment)
                    {
                        info.EnvironmentVariables.Add(env.Key.Substring(1, env.Key.Length - 2), env.Value);
                    }
                }

                // Log
                VCRServer.Log(LoggingLevel.Full, Properties.Resources.RunExtension, extension.FullName);

                // Start the process
                return(Process.Start(info));
            }
            catch (Exception e)
            {
                // Report
                VCRServer.Log(e);
            }

            // Report
            return(null);
        }
        /// <summary>
        /// Wendet eine Methode auf alle verwalteten Profile an.
        /// </summary>
        /// <param name="method">Die gewünschte Methode.</param>
        /// <param name="ignoreErrors">Gesetzt, wenn Fehler ignoriert werden sollen.</param>
        private void ForEachProfile(Action <ProfileState> method, bool ignoreErrors = false)
        {
            // Forward to all
            foreach (var state in m_profiles.Values)
            {
                try
                {
                    // Forward
                    method(state);
                }
                catch (Exception e)
                {
                    // Report
                    VCRServer.Log(e);

                    // See if we are allowed to ignore
                    if (!ignoreErrors)
                    {
                        throw;
                    }
                }
            }
        }
        /// <summary>
        /// Prüft, ob eine Datei in einem zulässigen Aufzeichnungsverzeichnis liegt.
        /// </summary>
        /// <param name="path">Der zu prüfende Dateipfad.</param>
        /// <returns>Gesetzt, wenn der Pfad gültig ist.</returns>
        public bool IsValidTarget(string path)
        {
            // Must habe a path
            if (string.IsNullOrEmpty(path))
            {
                return(false);
            }

            // Test it
            foreach (var allowed in TargetDirectories)
            {
                if (path.StartsWith(allowed.FullName, StringComparison.InvariantCultureIgnoreCase))
                {
                    // Silent create the directory
                    try
                    {
                        // Create the directory
                        Directory.CreateDirectory(Path.GetDirectoryName(path));

                        // Yeah
                        return(true);
                    }
                    catch (Exception e)
                    {
                        // Report
                        VCRServer.Log(e);

                        // Done
                        return(false);
                    }
                }
            }

            // No, not possible
            return(false);
        }
Esempio n. 12
0
        /// <summary>
        /// Beendet eine Aufzeichnung.
        /// </summary>
        /// <param name="scheduleIdentifier">Die eindeutige Kennung der Aufzeichnung.</param>
        public void EndRecording(Guid scheduleIdentifier)
        {
            // Protect current request against transistions
            lock (m_RequestLock)
            {
                // Attach to the current request
                var current = m_CurrentRequest;

                // See if it exists
                if (ReferenceEquals(current, null))
                {
                    // Report
                    VCRServer.Log(LoggingLevel.Errors, "Request to end Recording '{0}' but there is no active Recording Process", scheduleIdentifier);

                    // Better do it ourselves
                    Collection.ConfirmOperation(scheduleIdentifier, false);
                }
                else
                {
                    // Just stop
                    current.Stop(scheduleIdentifier);
                }
            }
        }
        /// <summary>
        /// Meldet, dass eine Aufzeichnung nun beginnen sollte.
        /// </summary>
        /// <param name="item">Die zu startende Aufzeichnung.</param>
        /// <param name="planner">Die Planungsinstanz.</param>
        /// <param name="context">Zusatzinformationen zur Aufzeichnungsplanung.</param>
        void IRecordingPlannerSite.Start(IScheduleInformation item, RecordingPlanner planner, PlanContext context)
        {
            // We are no longer active - simulate start and do nothing
            if (!m_plannerActive)
            {
                // Make planner believe we did it
                planner.Start(item);

                // Make sure that we wake up after the grace period
                if (PowerManager.IsSuspended && VCRConfiguration.Current.SuppressDelayAfterForcedHibernation)
                {
                    Tools.ExtendedLogging("Hibernation Delay is disabled and can not be enforced");
                }
                else
                {
                    m_timer.SecondsToWait = VCRConfiguration.Current.DelayAfterForcedHibernation.TotalSeconds;
                }

                // Done
                return;
            }

            // Report
            VCRServer.Log(LoggingLevel.Schedules, "Start recording '{0}'", item.Definition.Name);

            // Locate the profile - if we don't find it we are in big trouble!
            ProfileState profile;

            if (!m_profiles.TryGetValue(item.Resource.Name, out profile))
            {
                return;
            }

            // Mark as pending
            m_pendingSchedule = item;
            m_pendingStart    = true;

            // Create the recording
            var recording = VCRRecordingInfo.Create(item, context);

            // Check for EPG
            var guideUpdate = item.Definition as ProgramGuideTask;

            if (guideUpdate != null)
            {
                // Start a new guide collector
                m_pendingActions += ProgramGuideProxy.Create(profile, recording).Start;
            }
            else
            {
                // Check for PSI
                var sourceUpdate = item.Definition as SourceListTask;
                if (sourceUpdate != null)
                {
                    // Start a new update
                    m_pendingActions += SourceScanProxy.Create(profile, recording).Start;
                }
                else
                {
                    // Start a regular recording - profile will decide if to join an existing recording
                    m_pendingActions += () => profile.StartRecording(recording);
                }
            }
        }
 /// <summary>
 /// Meldet, dass eine Aufzeichnung nicht ausgeführt werden kann.
 /// </summary>
 /// <param name="item">Die nicht ausgeführte Aufzeichnung.</param>
 void IRecordingPlannerSite.Discard(IScheduleDefinition item)
 {
     // Report
     VCRServer.Log(LoggingLevel.Schedules, "Could not record '{0}'", item.Name);
 }
        /// <summary>
        /// Aktualisiert ständig die Planung.
        /// </summary>
        private void PlanThread()
        {
            // Always loop
            while (m_planThread != null)
            {
                // See if a new plan is requested
                lock (m_newPlanSync)
                    while (!m_newPlan)
                    {
                        if (m_planThread == null)
                        {
                            return;
                        }
                        else
                        {
                            Monitor.Wait(m_newPlanSync);
                        }
                    }

                // At least we accepted the request
                m_newPlan = false;

                // See if we still have a planner
                var planner = m_planner;
                if (planner == null)
                {
                    break;
                }

                // Just take a look what to do next
                using (PowerManager.StartForbidHibernation())
                    try
                    {
                        // Reset start actions
                        m_pendingActions = null;

                        // Protect planning.
                        lock (planner)
                        {
                            // Report
                            Tools.ExtendedLogging("Woke up for Plan Calculation at {0}", DateTime.Now);

                            // Retest
                            if (m_planThread == null)
                            {
                                break;
                            }

                            // See if we are allowed to take the next step in plan - we schedule only one activity at a time
                            if (m_pendingSchedule == null)
                            {
                                // Release our lock
                                AllowHibernation();

                                // Reset timer
                                if (PowerManager.IsSuspended && VCRConfiguration.Current.SuppressDelayAfterForcedHibernation)
                                {
                                    Tools.ExtendedLogging("VCR.NET is suspending - not updating Timer");
                                }
                                else
                                {
                                    m_timer.SecondsToWait = 0;
                                }

                                // Analyse plan
                                planner.DispatchNextActivity(DateTime.UtcNow);

                                // If we are shutting down better forget anything we did in the previous step - only timer setting matters!
                                if (!m_plannerActive)
                                {
                                    // Reset to initial state
                                    m_pendingSchedule = null;
                                    m_pendingActions  = null;
                                    m_pendingStart    = false;

                                    // And forget all allocations
                                    planner.Reset();

                                    // Just in case allow hibernation again
                                    AllowHibernation();
                                }
                            }
                        }

                        // Run start and stop actions outside the planning lock (to avoid deadlocks) but inside the hibernation protection (to forbid hibernation)
                        var toStart = m_pendingActions;
                        if (toStart != null)
                        {
                            toStart();
                        }
                    }
                    catch (Exception e)
                    {
                        // Report and ignore - we do not expect any error to occur
                        VCRServer.Log(e);
                    }

                // New plan is now available - beside termination this will do nothing at all but briefly aquiring an idle lock
                lock (m_planAvailableSync)
                    Monitor.PulseAll(m_planAvailableSync);
            }
        }
Esempio n. 16
0
        /// <summary>
        /// Der SCM möchte den VCR.NET Recording Service starten.
        /// </summary>
        /// <param name="args">Befehlszeilenparameter für den Start.</param>
        protected override void OnStart( string[] args )
        {
            // Fully save
            try
            {
                // Report
                Tools.ExtendedLogging( "SCM has requested a Service Start" );

                // Report delay
                if (!Tools.DebugMode)
                    RequestAdditionalTime( 300000 );

                // Create server instance
                VCRServer = new VCRServer( Tools.ApplicationDirectory.Parent );

                // Create web server instance
                m_WebServer = new WebServer.ServerHost( VCRServer );

                // Report
                Tools.ExtendedLogging( "Attaching Process" );

                // Get a token for this process
                IntPtr processToken;
                if (!OpenProcessToken( Process.GetCurrentProcess().Handle, 0x28, out processToken ))
                    return;

                // Report
                Tools.ExtendedLogging( "Aquiring Shutdown Privileges" );

                // Helper
                TokenPrivileges privileges = new TokenPrivileges();

                // Lookup the privilege value
                if (LookupPrivilegeValue( null, "SeShutdownPrivilege", out privileges.Luid ))
                {
                    // Finish
                    privileges.PrivilegeCount = 1;
                    privileges.Attributes = 2;

                    // Update
                    if (!AdjustTokenPrivileges( processToken, false, ref privileges, 0, IntPtr.Zero, IntPtr.Zero ))
                        VCRServer.Log( LoggingLevel.Security, EventLogEntryType.Warning, Properties.Resources.AquirePrivilegeFailed );
                }
                else
                {
                    // Report
                    VCRServer.Log( LoggingLevel.Security, EventLogEntryType.Error, Properties.Resources.LookupPrivilegeFailed );
                }

                // Release
                CloseHandle( processToken );

                // Report
                Tools.ExtendedLogging( "Web Server Start initiated from Thread {0}", Thread.CurrentThread.ManagedThreadId );

                // Create the web server on a separate thread
                m_webStarter = new Thread( () =>
                    {
                        // Be safe
                        try
                        {
                            // Report
                            Tools.ExtendedLogging( "Starting Web Server on Thread {0}", Thread.CurrentThread.ManagedThreadId );

                            // Start Web Server
                            m_WebServer.Start();
                        }
                        catch (Exception e)
                        {
                            // Report
                            EventLog.WriteEntry( e.ToString(), EventLogEntryType.Error );
                        }
                    } );

                // Start it
                m_webStarter.Start();

                // Report
                Tools.ExtendedLogging( "Final Initialisation started" );

                // Start our child process and report success
                VCRServer.Log( LoggingLevel.Full, Properties.Resources.ServiceStarted );

                // Register with power manager
                PowerManager.OnChanged += HibernationChanged;

                // Run initial scan
                PowerManager.OnResume();

                // Create hibernate thread
                m_HibernateHelper = new Thread( ReTestShutdown ) { Name = "Periodic Check for Hibernation" };
                m_HibernateHelper.Start();

                // Report
                Tools.ExtendedLogging( "Returning Control to SCM" );
            }
            catch (Exception e)
            {
                // Report
                Tools.LogException( "OnStart", e );

                // Process
                throw e;
            }
        }
Esempio n. 17
0
        /// <summary>
        /// Der SCM möchte den VCR.NET Recording Service starten.
        /// </summary>
        /// <param name="args">Befehlszeilenparameter für den Start.</param>
        protected override void OnStart(string[] args)
        {
            // Fully save
            try
            {
                // Report
                Tools.ExtendedLogging("SCM has requested a Service Start");

                // Report delay
                if (!Tools.DebugMode)
                {
                    RequestAdditionalTime(300000);
                }

                // Create server instance
                VCRServer = new VCRServer(Tools.ApplicationDirectory.Parent);

                // Create web server instance
                m_WebServer = new WebServer.ServerHost(VCRServer);

                // Report
                Tools.ExtendedLogging("Attaching Process");

                // Get a token for this process
                IntPtr processToken;
                if (!OpenProcessToken(Process.GetCurrentProcess().Handle, 0x28, out processToken))
                {
                    return;
                }

                // Report
                Tools.ExtendedLogging("Aquiring Shutdown Privileges");

                // Helper
                TokenPrivileges privileges = new TokenPrivileges();

                // Lookup the privilege value
                if (LookupPrivilegeValue(null, "SeShutdownPrivilege", out privileges.Luid))
                {
                    // Finish
                    privileges.PrivilegeCount = 1;
                    privileges.Attributes     = 2;

                    // Update
                    if (!AdjustTokenPrivileges(processToken, false, ref privileges, 0, IntPtr.Zero, IntPtr.Zero))
                    {
                        VCRServer.Log(LoggingLevel.Security, EventLogEntryType.Warning, Properties.Resources.AquirePrivilegeFailed);
                    }
                }
                else
                {
                    // Report
                    VCRServer.Log(LoggingLevel.Security, EventLogEntryType.Error, Properties.Resources.LookupPrivilegeFailed);
                }

                // Release
                CloseHandle(processToken);

                // Report
                Tools.ExtendedLogging("Web Server Start initiated from Thread {0}", Thread.CurrentThread.ManagedThreadId);

                // Create the web server on a separate thread
                m_webStarter = new Thread(() =>
                {
                    // Be safe
                    try
                    {
                        // Report
                        Tools.ExtendedLogging("Starting Web Server on Thread {0}", Thread.CurrentThread.ManagedThreadId);

                        // Start Web Server
                        m_WebServer.Start();
                    }
                    catch (Exception e)
                    {
                        // Report
                        EventLog.WriteEntry(e.ToString(), EventLogEntryType.Error);
                    }
                });

                // Start it
                m_webStarter.Start();

                // Report
                Tools.ExtendedLogging("Final Initialisation started");

                // Start our child process and report success
                VCRServer.Log(LoggingLevel.Full, Properties.Resources.ServiceStarted);

                // Register with power manager
                PowerManager.OnChanged += HibernationChanged;

                // Run initial scan
                PowerManager.OnResume();

                // Create hibernate thread
                m_HibernateHelper = new Thread(ReTestShutdown)
                {
                    Name = "Periodic Check for Hibernation"
                };
                m_HibernateHelper.Start();

                // Report
                Tools.ExtendedLogging("Returning Control to SCM");
            }
            catch (Exception e)
            {
                // Report
                Tools.LogException("OnStart", e);

                // Process
                throw e;
            }
        }