Provides a queue for data changes.
        /// <summary>
        /// Constructs a new instance.
        /// </summary>
        public DataChangeMonitoredItem(
            MonitoredNode source,
            uint id,
            uint attributeId,
            NumericRange indexRange,
            QualifiedName dataEncoding,
            DiagnosticsMasks diagnosticsMasks,
            TimestampsToReturn timestampsToReturn,
            MonitoringMode monitoringMode,
            uint clientHandle,
            double samplingInterval,
            uint queueSize,
            bool discardOldest,
            DataChangeFilter filter,
            Range range,
            bool alwaysReportUpdates)
        {
            m_source              = source;
            m_id                  = id;
            m_attributeId         = attributeId;
            m_indexRange          = indexRange;
            m_dataEncoding        = dataEncoding;
            m_timestampsToReturn  = timestampsToReturn;
            m_diagnosticsMasks    = diagnosticsMasks;
            m_monitoringMode      = monitoringMode;
            m_clientHandle        = clientHandle;
            m_samplingInterval    = samplingInterval;
            m_nextSampleTime      = DateTime.UtcNow.Ticks;
            m_readyToPublish      = false;
            m_readyToTrigger      = false;
            m_queue               = null;
            m_filter              = filter;
            m_range               = 0;
            m_alwaysReportUpdates = alwaysReportUpdates;

            if (range != null)
            {
                m_range = range.High - range.Low;
            }

            if (queueSize > 1)
            {
                m_queue = new MonitoredItemQueue(id);
                m_queue.SetQueueSize(queueSize, discardOldest, diagnosticsMasks);
                m_queue.SetSamplingInterval(samplingInterval);
            }
        }
		/// <summary>
		/// Clears and re-initializes the queue if the monitoring parameters changed.
		/// </summary>
        protected void InitializeQueue()
        {
			switch (m_monitoringMode)
			{
				default:
				case MonitoringMode.Disabled:
				{
                    m_queue = null;
                    m_events = null;
					break;
				}

                case MonitoringMode.Reporting:
                case MonitoringMode.Sampling:
                    {
                        // check if queuing is disabled.
                        if (m_queueSize == 0)
                        {
                            if (m_typeMask == MonitoredItemTypeMask.DataChange)
                            {
                                m_queueSize = 1;
                            }

                            if ((m_typeMask & MonitoredItemTypeMask.Events) != 0)
                            {
                                m_queueSize = 1000;
                            }
                        }

                        // create data queue.
                        if (m_typeMask == MonitoredItemTypeMask.DataChange)
                        {
                            if (m_queueSize <= 1)
                            {
                                m_queue = null;
                                break; // queueing is disabled
                            }

                            bool queueLastValue = false;

                            if (m_queue == null)
                            {
                                m_queue = new MonitoredItemQueue(m_id);
                                queueLastValue = true;
                            }

                            m_queue.SetQueueSize(m_queueSize, m_discardOldest, m_diagnosticsMasks);
                            m_queue.SetSamplingInterval(m_samplingInterval);

                            if (queueLastValue && m_lastValue != null)
                            {
                                m_queue.QueueValue(m_lastValue, m_lastError);
                            }
                        }
                        else // create event queue.
                        {
                            if (m_events == null)
                            {
                                m_events = new List<EventFieldList>();
                        }

                        // check if existing queue entries must be discarded;
                        if (m_events.Count > m_queueSize)
                        {
                            int queueSize = (int)m_queueSize;

                            if (m_discardOldest)
                            {
                                m_events.RemoveRange(0, m_events.Count - queueSize);
                            }
                            else
                            {
                                m_events.RemoveRange(queueSize, m_events.Count - queueSize);
                            }
                        }
                    }
                    
					break;
				}
			}
		}
        /// <summary>
        /// Constructs a new instance.
        /// </summary>
        public DataChangeMonitoredItem(
            MonitoredNode source,
            uint id,
            uint attributeId,
            NumericRange indexRange,
            QualifiedName dataEncoding,
            DiagnosticsMasks diagnosticsMasks,
            TimestampsToReturn timestampsToReturn,
            MonitoringMode monitoringMode,
            uint clientHandle,
            double samplingInterval,
            uint queueSize,
            bool discardOldest,
            DataChangeFilter filter,
            Range range,
            bool alwaysReportUpdates)
        {
            m_source = source;
            m_id = id;
            m_attributeId = attributeId;
            m_indexRange = indexRange;
            m_dataEncoding = dataEncoding;
            m_timestampsToReturn = timestampsToReturn;
            m_diagnosticsMasks = diagnosticsMasks;
            m_monitoringMode = monitoringMode;
            m_clientHandle = clientHandle;
            m_samplingInterval = samplingInterval;
            m_nextSampleTime = DateTime.UtcNow.Ticks;
            m_readyToPublish = false;
            m_readyToTrigger = false;
            m_queue = null;
            m_filter = filter;
            m_range = 0;
            m_alwaysReportUpdates = alwaysReportUpdates;
        
            if (range != null)
            {
                m_range = range.High  - range.Low;
            }

            if (queueSize > 1)
            {
                m_queue = new MonitoredItemQueue(id);
                m_queue.SetQueueSize(queueSize, discardOldest, diagnosticsMasks);
                m_queue.SetSamplingInterval(samplingInterval);
            }
        }
        /// <summary>
        /// Modifies the monitored item parameters,
        /// </summary>
        public ServiceResult Modify(
            DiagnosticsMasks diagnosticsMasks,
            TimestampsToReturn timestampsToReturn,
            uint clientHandle,
            double samplingInterval,
            uint queueSize,
            bool discardOldest,
            DataChangeFilter filter,
            Range range)
        {
            lock (m_lock)
            {
                m_diagnosticsMasks   = diagnosticsMasks;
                m_timestampsToReturn = timestampsToReturn;
                m_clientHandle       = clientHandle;

                // subtract the previous sampling interval.
                long oldSamplingInterval = (long)(m_samplingInterval * TimeSpan.TicksPerMillisecond);

                if (oldSamplingInterval < m_nextSampleTime)
                {
                    m_nextSampleTime -= oldSamplingInterval;
                }

                m_samplingInterval = samplingInterval;

                // calculate the next sampling interval.
                long newSamplingInterval = (long)(m_samplingInterval * TimeSpan.TicksPerMillisecond);

                if (m_samplingInterval > 0)
                {
                    m_nextSampleTime += newSamplingInterval;
                }
                else
                {
                    m_nextSampleTime = 0;
                }

                // update the filter and the range.
                m_filter = filter;
                m_range  = 0;

                if (range != null)
                {
                    m_range = range.High - range.Low;
                }

                // update the queue size.
                if (queueSize > 1)
                {
                    if (m_queue == null)
                    {
                        m_queue = new MonitoredItemQueue(m_id);
                    }

                    m_queue.SetQueueSize(queueSize, discardOldest, diagnosticsMasks);
                    m_queue.SetSamplingInterval(samplingInterval);
                }
                else
                {
                    m_queue = null;
                }

                return(ServiceResult.Good);
            }
        }
        /// <summary>
        /// Modifies the monitored item parameters,
        /// </summary>
        public ServiceResult Modify(
            DiagnosticsMasks diagnosticsMasks,
            TimestampsToReturn timestampsToReturn,
            uint clientHandle,
            double samplingInterval,
            uint queueSize,
            bool discardOldest,
            DataChangeFilter filter,
            Range range)
        {
            lock (m_lock)
            {
                m_diagnosticsMasks = diagnosticsMasks;
                m_timestampsToReturn = timestampsToReturn;
                m_clientHandle = clientHandle;

                // subtract the previous sampling interval.
                long oldSamplingInterval = (long)(m_samplingInterval*TimeSpan.TicksPerMillisecond);

                if (oldSamplingInterval < m_nextSampleTime)
                {
                    m_nextSampleTime -= oldSamplingInterval;
                }
                
                m_samplingInterval = samplingInterval;

                // calculate the next sampling interval.                
                long newSamplingInterval = (long)(m_samplingInterval*TimeSpan.TicksPerMillisecond);

                if (m_samplingInterval > 0)
                {
                    m_nextSampleTime += newSamplingInterval;
                }
                else
                {
                    m_nextSampleTime = 0;
                }

                // update the filter and the range.
                m_filter = filter;
                m_range = 0;

                if (range != null)
                {
                    m_range = range.High  - range.Low;
                }

                // update the queue size.
                if (queueSize > 1)
                {
                    if (m_queue == null)
                    {
                        m_queue = new MonitoredItemQueue(m_id);
                    }

                    m_queue.SetQueueSize(queueSize, discardOldest, diagnosticsMasks);
                    m_queue.SetSamplingInterval(samplingInterval);
                }
                else
                {
                    m_queue = null;
                }

                return ServiceResult.Good;
            }
        }