Ejemplo n.º 1
0
            /// <summary>
            /// Prüft, ob ein weiterer Zeitpunkt vorliegt.
            /// </summary>
            public void MoveNext()
            {
                // As long as necessary
                for (; ;)
                {
                    // Ask base
                    if (m_Scan != null)
                    {
                        if (!m_Scan.MoveNext())
                        {
                            m_Scan = null;
                        }
                    }

                    // Report
                    if (m_Scan == null)
                    {
                        break;
                    }

                    // Load what base gives us
                    m_Current = m_Scan.Current;

                    // Load to check - normally we will not change it
                    var planned = m_Current.Planned;

                    // Find exception to apply
                    PlanException exception;
                    if (m_Exceptions.TryGetValue(planned.Start.ToLocalTime().Date, out exception))
                    {
#if !SILVERLIGHT
                        // Report
                        if (RecordingScheduler.SchedulerTrace.TraceVerbose)
                        {
                            Trace.TraceInformation(Properties.SchedulerResources.Trace_Exception, planned.Start, planned.Duration, exception.StartDelta, exception.DurationDelta);
                        }
#endif

                        // Change
                        planned =
                            new PlannedTime
                        {
                            Duration = planned.Duration + exception.DurationDelta,
                            Start    = planned.Start + exception.StartDelta,
                        };

                        // Write back
                        m_Current.Planned = planned;
                    }

                    // Found it
                    if (planned.End > m_MinTime)
                    {
                        if (planned.Duration.TotalSeconds > 0)
                        {
                            break;
                        }
                    }
                }
            }
Ejemplo n.º 2
0
 /// <summary>
 /// Erzeugt eine neue Beschreibung.
 /// </summary>
 /// <param name="map">Die zugehörige Verwaltung einer Ressource.</param>
 /// <param name="source">Die Quelle, die verwendet werden soll.</param>
 /// <param name="plan">Die ursprüngliche Planung.</param>
 /// <param name="index">Der erste Eintrag in der Verwaltung, der belegt werden soll.</param>
 public AllocationPlan(AllocationMap map, IScheduleSource source, SuggestedPlannedTime plan, int index)
 {
     // Remember
     m_allocationIndex = index;
     m_source          = source;
     m_plan            = plan;
     m_map             = map;
 }
Ejemplo n.º 3
0
        /// <summary>
        /// Fordert eine Entschlüsselung an.
        /// </summary>
        /// <param name="source">Die zu verwendende Quelle.</param>
        /// <param name="timeHolder">Der Zeitraum, für den die Planung stattfinden soll.</param>
        /// <returns>Gesetzt, wenn eine Zuordnung überhaupt möglich ist. Gemeldet wird dann der Zeitversatz der Zuordnung.</returns>
        public AllocationPlan PrepareAllocation(IScheduleSource source, SuggestedPlannedTime timeHolder)
        {
            // Extract the time to use for plannung
            var time = timeHolder.Planned;

            // As long as needed
            for (var scanStart = 0; ;)
            {
                // See if there is at least one allocation area available
                var allocationIndex = m_Allocations.FindIndex(scanStart, a => a.Overlaps(time));
                if (allocationIndex < 0)
                {
                    return(null);
                }

                // On the start skip all having no recording left
                while (!m_Allocations[allocationIndex].CanAllocate(source))
                {
                    if (++allocationIndex == m_Allocations.Count)
                    {
                        return(null);
                    }
                    else if (!m_Allocations[allocationIndex].Overlaps(time))
                    {
                        return(null);
                    }
                }

                // Initial index - where we start the allocation
                var startIndex = allocationIndex;

                // Now make sure that we can record to the end - allocation maps from the beginning to the end of all times
                while (++allocationIndex < m_Allocations.Count)
                {
                    if (!m_Allocations[allocationIndex].Overlaps(time))
                    {
                        break;
                    }
                    else if (!m_Allocations[allocationIndex].CanAllocate(source))
                    {
                        // Prepare to rescan
                        scanStart = allocationIndex + 1;

                        // Do not end
                        startIndex = -1;

                        // Done with loop
                        break;
                    }
                }

                // Response
                if (startIndex >= 0)
                {
                    return(new AllocationPlan(this, source, timeHolder, startIndex));
                }
            }
        }
Ejemplo n.º 4
0
            /// <summary>
            /// Erzeugt eine Planungsinstanz basierend auf den aktuell bekannten Aufzeichnungen.
            /// </summary>
            /// <returns>Der gewünschte Plan.</returns>
            private SchedulePlan CreateSchedulePlan()
            {
                // Create
                var plan = new SchedulePlan(m_Resources);

                // Report
                var resources = plan.Resources.ToDictionary(r => r.Resource, ReferenceComparer <IScheduleResource> .Default);

                // Merge in each schedule
                foreach (var recording in m_Recordings)
                {
                    // Attach to the resource
                    var resource     = recording.Resource;
                    var resourcePlan = resources[resource];

                    // Check mode
                    if (recording.Source == null)
                    {
                        // Try to reserve
                        if (!resourcePlan.Reserve(recording.Time.End))
                        {
                            return(null);
                        }

                        // Next
                        continue;
                    }

                    // Attach to the timing
                    SuggestedPlannedTime planned = recording.Time;

                    // Try add
                    if (!resourcePlan.Add(recording, planned, DateTime.MinValue))
                    {
                        return(null);
                    }

                    // Must not start late
                    if (planned.Planned.Start != recording.Time.Start)
                    {
                        return(null);
                    }
                }

                // Report
                return(plan);
            }
Ejemplo n.º 5
0
        /// <summary>
        /// Prüft, ob eine Aufzeichnung ergänzt werden kann.
        /// </summary>
        /// <param name="recording">Die neue Aufzeichnung.</param>
        /// <param name="time">Der Zeitraum der neuen Aufzeichnung.</param>
        /// <param name="minTime">Die Aufzeichnung darf auf keinen Fall vor diesem Zeitpunkt beginnen.</param>
        /// <returns>Gesetzt, wenn eine Aufzeichnung möglich war.</returns>
        /// <exception cref="ArgumentNullException">Es wurde keine Aufzeichnung übergeben.</exception>
        /// <exception cref="ArgumentOutOfRangeException">Die Startzeit liegt vor der Aktivierung des Gerätes.</exception>
        public bool Add(IRecordingDefinition recording, SuggestedPlannedTime time, DateTime minTime)
        {
            // Validate
            if (recording == null)
            {
                throw new ArgumentNullException("recording");
            }

            // If the current resource can see the source we can do nothing at all
            var resource = Resource;

            if (!resource.CanAccess(recording.Source))
            {
                return(false);
            }

            // If the recording is bound to dedicated sources but not use we should not process
            var allowedResources = recording.Resources;

            if (allowedResources != null)
            {
                if (allowedResources.Length > 0)
                {
                    if (!allowedResources.Any(r => ReferenceEquals(r, resource)))
                    {
                        return(false);
                    }
                }
            }

            // See if we have to cut it off and load the corresponding end of the recording
            var initialPlan = time.Planned;

            // Clip to minimum allowed
            if (time.Planned.Start < minTime)
            {
                // Not possible at all - should never ever be requested but better be safe
                if (time.Planned.End <= minTime)
                {
                    return(false);
                }

                // Correct the parameters - end is calculated from start and duration
                time.Planned.Duration = time.Planned.End - minTime;
                time.Planned.Start    = minTime;
            }

            // See if device could at least receive
            var sourceAllocation = Allocations.PrepareAllocation(recording.Source, time);

            if (sourceAllocation == null)
            {
                return(false);
            }

            // Add it - will clip the time accordingly
            sourceAllocation.Allocate();

            // Time to check for encryption - technically it should not be possible to have a recording on a source which is for some time encypted and for some other time not but better be safe
            if (recording.Source.IsEncrypted)
            {
                // What to check for
                var counters = DecryptionCounters.Select(i => SchedulePlan.DecryptionCounters[i]).ToArray();

                // Check all
                foreach (var counter in counters)
                {
                    if (counter.PrepareAllocation(recording.Source, time) == null)
                    {
                        return(false);
                    }
                }

                // Now reserve all - this may manipulate the time slice for the recording as well
                foreach (var counter in counters)
                {
                    // Allocate again - we may only call the allocate immediatly after preparing
                    var allocation = counter.PrepareAllocation(recording.Source, time);
                    if (allocation == null)
                    {
                        throw new InvalidOperationException("PrepareAllocation");
                    }

                    // Process
                    allocation.Allocate();
                }
            }

            // Remember recording
            m_Recordings.Add(new _RecordingItem(recording, time.Planned, time.Planned.Start > initialPlan.Start));

            // Get cut time
            var delta = initialPlan.Duration - time.Planned.Duration;

            // Adjust cut time - this will be taken in account when checking weights to get the best plan
            TotalCut += delta;

            // Count failures
            if (delta.Ticks > 0)
            {
                CutRecordings += 1;
            }

            // We did it
            return(true);
        }
            /// <summary>
            /// Prüft, ob ein weiterer Zeitpunkt vorliegt.
            /// </summary>
            public void MoveNext()
            {
                // As long as necessary
                for (; ; )
                {
                    // Ask base
                    if (m_Scan != null)
                        if (!m_Scan.MoveNext())
                            m_Scan = null;

                    // Report
                    if (m_Scan == null)
                        break;

                    // Load what base gives us
                    m_Current = m_Scan.Current;

                    // Load to check - normally we will not change it
                    var planned = m_Current.Planned;

                    // Find exception to apply         
                    PlanException exception;
                    if (m_Exceptions.TryGetValue( planned.Start.ToLocalTime().Date, out exception ))
                    {
#if !SILVERLIGHT
                        // Report
                        if (RecordingScheduler.SchedulerTrace.TraceVerbose)
                            Trace.TraceInformation( Properties.SchedulerResources.Trace_Exception, planned.Start, planned.Duration, exception.StartDelta, exception.DurationDelta );
#endif

                        // Change
                        planned =
                            new PlannedTime
                            {
                                Duration = planned.Duration + exception.DurationDelta,
                                Start = planned.Start + exception.StartDelta,
                            };

                        // Write back
                        m_Current.Planned = planned;
                    }

                    // Found it
                    if (planned.End > m_MinTime)
                        if (planned.Duration.TotalSeconds > 0)
                            break;
                }
            }
        /// <summary>
        /// Meldet alle Aufzeichnungen ab einem bestimmten Zeitpunkt.
        /// </summary>
        /// <param name="minTime">Alle Aufzeichnungen, die vor diesem Zeitpunkt enden, werden
        /// nicht berücksichtigt. Die Angabe erfolgt in UTC / GMT Notation.</param>
        /// <returns>Alle Aufzeichnungen.</returns>
        private IEnumerable <ScheduleInfo> GetSchedulesForRecordings(DateTime minTime)
        {
            // All items to process
            var items = new _ScheduleList(m_PlanItems.Where(r => !m_ForbiddenDefinitions.Contains(r.Definition.UniqueIdentifier)), minTime);

            // Create the plans to extend
            var plans = new List <SchedulePlan> {
                m_PlanCreator()
            };
            var steps = 0;

            // As long as necessary
            while (items.MoveNext())
            {
                // Load the item
                var candidate    = items.Current;
                var candiateTime = candidate.Current;
                var planned      = candiateTime.Planned;

#if !SILVERLIGHT
                // Report
                if (SchedulerTrace.TraceVerbose)
                {
                    Trace.TraceInformation(Properties.SchedulerResources.Trace_Candidate, candidate.Definition.Source, planned.Start, planned.Duration);
                }
#endif

                // Get the current end of plans and see if we can dump the state - this may increase performance
                var planStart   = plans.SelectMany(p => p.Resources).Min(r => (DateTime?)r.PlanStart);
                var planEnd     = plans.SelectMany(p => p.Resources).Max(r => (DateTime?)r.PlanEnd);
                var canEndPlan  = planEnd.HasValue && (planEnd.Value != DateTime.MinValue) && (planned.Start >= planEnd.Value);
                var mustEndPlan = planStart.HasValue && (planStart.Value != DateTime.MaxValue) && planEnd.HasValue && (planEnd.Value != DateTime.MinValue) && ((planEnd.Value - planStart.Value).TotalDays > 2);

                // Count this effort
                if ((++steps > MaximumRecordingsInPlan) || canEndPlan || mustEndPlan || (plans.Count > MaximumAlternativesInPlan))
                {
                    // Find best plan
                    var best = SchedulePlan.FindBest(plans, m_comparer);

                    // Report
                    foreach (var info in Dump(best))
                    {
                        yield return(info);
                    }

                    // Reset
                    plans.Clear();
                    plans.Add(best.Restart(planned.Start));

                    // Reset
                    steps = 1;
                }

#if !SILVERLIGHT
                // Report
                if (SchedulerTrace.TraceVerbose)
                {
                    Trace.TraceInformation(Properties.SchedulerResources.Trace_PlanCount, plans.Count);
                }
#endif

                // All plans to extend
                var allPlans = plans.ToArray();

                // Discard list
                plans.Clear();

                // Iterate over all plans and try to add the current candidate - in worst case this will multiply possible plans by the number of resources available
                foreach (var plan in allPlans)
                {
                    for (int i = plan.Resources.Length; i-- > 0;)
                    {
                        // Clone of plan must be recreated for each resource because test is allowed to modify it
                        var clone = plan.Clone();

                        // Remember the time we tried - implicit cast is important, do NOT use var
                        SuggestedPlannedTime plannedTime = planned;

                        // See if resource can handle this
                        if (clone.Resources[i].Add(candidate.Definition, plannedTime, minTime))
                        {
                            plans.Add(clone);
                        }
                    }
                }

                // Must reset if the recording could not be scheduled at all
                if (plans.Count < 1)
                {
                    // Report
                    yield return(new ScheduleInfo(candidate.Definition, null, planned, false));

                    // Restore the original plans since we did nothing at all
                    plans.AddRange(allPlans);
                }
            }

            // Send all we found
            foreach (var info in Dump(SchedulePlan.FindBest(plans, m_comparer)))
            {
                yield return(info);
            }
        }