The interface that a server exposes to objects that it contains.
Beispiel #1
0
        /// <summary>
        /// Publishes a value.
        /// </summary>
        private void Publish(
            OperationContext context,
            DataValue value,
            ServiceResult error,
            Queue <MonitoredItemNotification> notifications,
            Queue <DiagnosticInfo> diagnostics)
        {
            // set semantics changed bit.
            if (m_semanticsChanged)
            {
                if (value != null)
                {
                    value.StatusCode = value.StatusCode.SetSemanticsChanged(true);
                }

                if (error != null)
                {
                    error = new ServiceResult(
                        error.StatusCode.SetSemanticsChanged(true),
                        error.SymbolicId,
                        error.NamespaceUri,
                        error.LocalizedText,
                        error.AdditionalInfo,
                        error.InnerResult);
                }

                m_semanticsChanged = false;
            }

            // set structure changed bit.
            if (m_structureChanged)
            {
                if (value != null)
                {
                    value.StatusCode = value.StatusCode.SetStructureChanged(true);
                }

                if (error != null)
                {
                    error = new ServiceResult(
                        error.StatusCode.SetStructureChanged(true),
                        error.SymbolicId,
                        error.NamespaceUri,
                        error.LocalizedText,
                        error.AdditionalInfo,
                        error.InnerResult);
                }

                m_structureChanged = false;
            }

            // copy data value.
            MonitoredItemNotification item = new MonitoredItemNotification();

            item.ClientHandle = m_clientHandle;
            item.Value        = value;

            // apply timestamp filter.
            if (m_timestampsToReturn != TimestampsToReturn.Server && m_timestampsToReturn != TimestampsToReturn.Both)
            {
                item.Value.ServerTimestamp = DateTime.MinValue;
            }

            if (m_timestampsToReturn != TimestampsToReturn.Source && m_timestampsToReturn != TimestampsToReturn.Both)
            {
                item.Value.SourceTimestamp = DateTime.MinValue;
            }

            notifications.Enqueue(item);

            // update diagnostic info.
            DiagnosticInfo diagnosticInfo = null;

            if (m_lastError != null)
            {
                if ((m_diagnosticsMasks & DiagnosticsMasks.OperationAll) != 0)
                {
                    diagnosticInfo = ServerUtils.CreateDiagnosticInfo(m_source.Server, context, m_lastError);
                }
            }

            diagnostics.Enqueue(diagnosticInfo);
        }
        /// <summary>
        /// Adds the value to the queue. Discards values if the queue is full.
        /// </summary>
        /// <param name="value">The value to add.</param>
        /// <param name="error">The error to add.</param>
        private void Enqueue(DataValue value, ServiceResult error)
        {
            // check for empty queue.
            if (m_start < 0)
            {
                m_start    = 0;
                m_end      = 1;
                m_overflow = -1;

                // Utils.Trace("ENQUEUE VALUE: Value={0}", value.WrappedValue);

                m_values[m_start] = value;

                if (m_errors != null)
                {
                    m_errors[m_start] = error;
                }

                return;
            }

            int next = m_end;

            // check if the latest value has initial dummy data
            if (m_values[m_end - 1].StatusCode != StatusCodes.BadWaitingForInitialData)
            {
                // check for wrap around.
                if (next >= m_values.Length)
                {
                    next = 0;
                }

                // check if queue is full.
                if (m_start == next)
                {
                    if (!m_discardOldest)
                    {
                        m_overflow = m_end - 1;
                        ServerUtils.ReportDiscardedValue(null, m_monitoredItemId, value);

                        // overwrite last value
                        m_values[m_overflow] = value;

                        if (m_errors != null)
                        {
                            m_errors[m_overflow] = error;
                        }

                        return;
                    }

                    // remove oldest value.
                    m_start++;

                    if (m_start >= m_values.Length)
                    {
                        m_start = 0;
                    }

                    // set overflow bit.
                    m_overflow = m_start;
                    ServerUtils.ReportDiscardedValue(null, m_monitoredItemId, m_values[m_overflow]);
                }
                else
                {
                    // Utils.Trace("ENQUEUE VALUE: Value={0}", value.WrappedValue);
                }
            }
            else
            {
                // overwrite the last value
                next = m_end - 1;
            }

            // add value.
            m_values[next] = value;

            if (m_errors != null)
            {
                m_errors[next] = error;
            }

            m_end = next + 1;
        }
Beispiel #3
0
        /// <summary>
        /// Processes acknowledgements for previously published messages.
        /// </summary>
        public void Acknowledge(
            OperationContext context,
            SubscriptionAcknowledgementCollection subscriptionAcknowledgements,
            out StatusCodeCollection acknowledgeResults,
            out DiagnosticInfoCollection acknowledgeDiagnosticInfos)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (subscriptionAcknowledgements == null)
            {
                throw new ArgumentNullException(nameof(subscriptionAcknowledgements));
            }

            lock (m_lock)
            {
                bool diagnosticsExist = false;
                acknowledgeResults         = new StatusCodeCollection(subscriptionAcknowledgements.Count);
                acknowledgeDiagnosticInfos = new DiagnosticInfoCollection(subscriptionAcknowledgements.Count);

                for (int ii = 0; ii < subscriptionAcknowledgements.Count; ii++)
                {
                    SubscriptionAcknowledgement acknowledgement = subscriptionAcknowledgements[ii];

                    bool found = false;

                    for (int jj = 0; jj < m_queuedSubscriptions.Count; jj++)
                    {
                        QueuedSubscription subscription = m_queuedSubscriptions[jj];

                        if (subscription.Subscription.Id == acknowledgement.SubscriptionId)
                        {
                            ServiceResult result = subscription.Subscription.Acknowledge(context, acknowledgement.SequenceNumber);

                            if (ServiceResult.IsGood(result))
                            {
                                acknowledgeResults.Add(StatusCodes.Good);

                                if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                                {
                                    acknowledgeDiagnosticInfos.Add(null);
                                }
                            }
                            else
                            {
                                acknowledgeResults.Add(result.Code);

                                if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                                {
                                    DiagnosticInfo diagnosticInfo = ServerUtils.CreateDiagnosticInfo(m_server, context, result);
                                    acknowledgeDiagnosticInfos.Add(diagnosticInfo);
                                    diagnosticsExist = true;
                                }
                            }

                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        ServiceResult result = new ServiceResult(StatusCodes.BadSubscriptionIdInvalid);
                        acknowledgeResults.Add(result.Code);

                        if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                        {
                            DiagnosticInfo diagnosticInfo = ServerUtils.CreateDiagnosticInfo(m_server, context, result);
                            acknowledgeDiagnosticInfos.Add(diagnosticInfo);
                            diagnosticsExist = true;
                        }
                    }
                }

                if (!diagnosticsExist)
                {
                    acknowledgeDiagnosticInfos.Clear();
                }
            }
        }