Stores information used while a thread is completing an operation on behalf of a client.
Inheritance: IOperationContext
Exemple #1
0
        /// <summary>
        /// Creates a new instance of a sampling group.
        /// </summary>
        public SamplingGroup(
            IServerInternal         server,
            INodeManager            nodeManager,
            List<SamplingRateGroup> samplingRates,
            OperationContext        context,
            double                  samplingInterval)
        {
            if (server == null)        throw new ArgumentNullException("server");
            if (nodeManager == null)   throw new ArgumentNullException("nodeManager");
            if (samplingRates == null) throw new ArgumentNullException("samplingRates");

            m_server           = server;
            m_nodeManager      = nodeManager;
            m_samplingRates    = samplingRates;
            m_session          = context.Session;
            m_diagnosticsMask  = (DiagnosticsMasks)context.DiagnosticsMask & DiagnosticsMasks.OperationAll;
            m_samplingInterval = AdjustSamplingInterval(samplingInterval);

            m_itemsToAdd    = new List<ISampledDataChangeMonitoredItem>();
            m_itemsToRemove = new List<ISampledDataChangeMonitoredItem>();
            m_items         = new Dictionary<uint, ISampledDataChangeMonitoredItem>();

            // create a event to signal shutdown.
            m_shutdownEvent = new ManualResetEvent(true);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="SystemContext"/> class.
 /// </summary>
 /// <param name="server">The server.</param>
 /// <param name="context">The context.</param>
 public ServerSystemContext(IServerInternal server, OperationContext context)
 {
     OperationContext = context;
     NamespaceUris = server.NamespaceUris;
     ServerUris = server.ServerUris;
     TypeTable = server.TypeTree;
     EncodeableFactory = server.Factory;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="AsyncPublishOperation"/> class.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="request">The request.</param>
 /// <param name="server">The server.</param>
 public AsyncPublishOperation(
      OperationContext context,
      IEndpointIncomingRequest request,
      StandardServer server)
 {
     m_context = context;
     m_request = request;
     m_server = server;
     m_response = new PublishResponse();
     m_request.Calldata = this;
 }
Exemple #4
0
        /// <summary>
        /// Handles the GetWheels test method.
        /// </summary>
        public Wheel[] OnGetWheels(OperationContext context, NodeSource target, Vehicle vehicle)
        {
            GenericEvent e = GenericEvent.Construct(Server, new NodeId(ObjectTypes.MaintenanceEventType, GetNamespaceIndex(Namespaces.Sample)));
            
            e.InitializeNewEvent();
            e.Message.Value = "Some unknown problem.";
            e.SetProperty(new QualifiedName(BrowseNames.MustCompleteByDate, GetNamespaceIndex(Namespaces.Sample)), new DateTime(1987,2,3));
            
            ReportEvent(e);

            return vehicle.Wheels.ToArray();
        }
Exemple #5
0
        /// <summary>
        /// Subscribes or unsubscribes to events produced by all event sources.
        /// </summary>
        /// <remarks>
        /// This method is called when a event subscription is created or deleted. The node
        /// manager must start/stop reporting events for all objects that it manages.
        /// </remarks>
        public override ServiceResult SubscribeToAllEvents(
            Opc.Ua.Server.OperationContext context,
            uint subscriptionId,
            IEventMonitoredItem monitoredItem,
            bool unsubscribe)
        {
            ServerSystemContext serverSystemContext = SystemContext.Copy(context);

            lock (Lock)
            {
                // A client has subscribed to the Server object which means all events produced
                // by this manager must be reported. This is done by incrementing the monitoring
                // reference count for all root notifiers.
                if (_rootNotifiers != null)
                {
                    for (int ii = 0; ii < _rootNotifiers.Count; ii++)
                    {
                        SubscribeToEvents(serverSystemContext, _rootNotifiers[ii], monitoredItem, unsubscribe);
                    }
                }

                return(ServiceResult.Good);
            }
        }
        /// <summary>
        /// Returns all available notifications.
        /// </summary>
        private NotificationMessage InnerPublish(
            OperationContext      context, 
            out UInt32Collection  availableSequenceNumbers, 
            out bool              moreNotifications)
        {   
            // check session.
            VerifySession(context);

            // TraceState("PUBLISH");

            // check if a keep alive should be sent if there is no data.
            bool keepAliveIfNoData = (m_keepAliveCounter >= m_maxKeepAliveCount);

            availableSequenceNumbers = new UInt32Collection();

            moreNotifications = false;

            if (m_lastSentMessage < m_sentMessages.Count)
            {
                // return the available sequence numbers.
                for (int ii = 0; ii <= m_lastSentMessage && ii < m_sentMessages.Count; ii++)
                {
                    availableSequenceNumbers.Add(m_sentMessages[ii].SequenceNumber);
                }
                
                moreNotifications = m_waitingForPublish = m_lastSentMessage < m_sentMessages.Count-1;

                // TraceState("PUBLISH QUEUED MESSAGE");
                return m_sentMessages[m_lastSentMessage++];
            }
            
            List<NotificationMessage> messages = new List<NotificationMessage>();

            if (m_publishingEnabled)
            {                
                DateTime start1 = DateTime.UtcNow;

                // collect notifications to publish.
                Queue<EventFieldList> events = new Queue<EventFieldList>();
                Queue<MonitoredItemNotification> datachanges = new Queue<MonitoredItemNotification>();
                Queue<DiagnosticInfo> datachangeDiagnostics = new Queue<DiagnosticInfo>();
                
                // check for monitored items that are ready to publish.
                LinkedListNode<IMonitoredItem> current = m_itemsToPublish.First;
                
                while (current != null)
                {
                    LinkedListNode<IMonitoredItem> next = current.Next;
                    IMonitoredItem monitoredItem = current.Value;

                    if ((monitoredItem.MonitoredItemType & MonitoredItemTypeMask.DataChange) != 0)
                    {
                        ((IDataChangeMonitoredItem)monitoredItem).Publish(context, datachanges, datachangeDiagnostics);
                    }
                    else
                    {
                        ((IEventMonitoredItem)monitoredItem).Publish(context, events);                        
                    }

                    // add back to list to check.
                    m_itemsToPublish.Remove(current);
                    m_itemsToCheck.AddLast(current);
                                    
                    // check there are enough notifications for a message.
                    if (m_maxNotificationsPerPublish > 0 && events.Count + datachanges.Count > m_maxNotificationsPerPublish)
                    {
                        // construct message.
                        int notificationCount;
                        int eventCount = events.Count;
                        int dataChangeCount = datachanges.Count;
                                           
                        NotificationMessage message = ConstructMessage(
                             events, 
                             datachanges, 
                             datachangeDiagnostics, 
                             out notificationCount);

                        // add to list of messages to send.
                        messages.Add(message);

                        lock (m_diagnostics)
                        {
                            m_diagnostics.DataChangeNotificationsCount += (uint)(dataChangeCount - datachanges.Count);
                            m_diagnostics.EventNotificationsCount += (uint)(eventCount - events.Count);
                            m_diagnostics.NotificationsCount += (uint)notificationCount;
                        }
                    }
                                        
                    current = next;
                }
                    
                // pubish the remaining notifications.
                while (events.Count + datachanges.Count > 0)
                {
                    // construct message.
                    int notificationCount;
                    int eventCount = events.Count;
                    int dataChangeCount = datachanges.Count;   
                                       
                     NotificationMessage message = ConstructMessage(
                         events, 
                         datachanges, 
                         datachangeDiagnostics, 
                         out notificationCount);

                    // add to list of messages to send.
                    messages.Add(message);

                    lock (m_diagnostics)
                    {
                        m_diagnostics.DataChangeNotificationsCount += (uint)(dataChangeCount - datachanges.Count);
                        m_diagnostics.EventNotificationsCount += (uint)(eventCount - events.Count);
                        m_diagnostics.NotificationsCount += (uint)notificationCount;
                    }
                }

                // check for missing notifications.
                if (!keepAliveIfNoData && messages.Count == 0)
                {
                    Utils.Trace(
                        (int)Utils.TraceMasks.Error,
                        "Oops! MonitoredItems queued but no notifications availabled.");
               
                    m_waitingForPublish = false;

                    return null;
                }
                
                DateTime end1 = DateTime.UtcNow;
                
                double delta1 = ((double)(end1.Ticks-start1.Ticks))/TimeSpan.TicksPerMillisecond;

                if (delta1 > 200)
                {
                    TraceState(Utils.Format("PUBLISHING DELAY ({0}ms)", delta1));
                }
            }

            if (messages.Count == 0)
            {
                // create a keep alive message.
                NotificationMessage message = new NotificationMessage();

                // use the sequence number for the next message.                    
                message.SequenceNumber = (uint)m_sequenceNumber; 
                message.PublishTime    = DateTime.UtcNow;

                // return the available sequence numbers.
                for (int ii = 0; ii <= m_lastSentMessage && ii < m_sentMessages.Count; ii++)
                {
                    availableSequenceNumbers.Add(m_sentMessages[ii].SequenceNumber);
                }

                // TraceState("PUBLISH KEEPALIVE");
                return message;
            }

            // have to drop unsent messages if out of queue space.
            if (messages.Count > m_maxMessageCount)
            {
                Utils.Trace(
                    "WARNING: QUEUE OVERFLOW. Dropping {2} Messages. Increase MaxMessageQueueSize. SubId={0}, MaxMessageQueueSize={1}", 
                    m_id,
                    m_maxMessageCount,
                    messages.Count - (int)m_maxMessageCount);

                messages.RemoveRange(0, messages.Count - (int)m_maxMessageCount);
            }

            // remove old messages if queue is full.
            if (m_sentMessages.Count > m_maxMessageCount - messages.Count)
            {
                lock (m_diagnostics)
                {
                    m_diagnostics.UnacknowledgedMessageCount += (uint)messages.Count;
                }

                if (m_maxMessageCount <= messages.Count)
                {
                    m_sentMessages.Clear();
                }
                else
                {
                    m_sentMessages.RemoveRange(0, messages.Count);
                }
            }

            // save new message
            m_lastSentMessage = m_sentMessages.Count;
            m_sentMessages.AddRange(messages);
            
            // check if there are more notifications to send.
            moreNotifications = m_waitingForPublish = messages.Count > 1;

            // return the available sequence numbers.
            for (int ii = 0; ii <= m_lastSentMessage && ii < m_sentMessages.Count; ii++)
            {
                availableSequenceNumbers.Add(m_sentMessages[ii].SequenceNumber);
            }

            // TraceState("PUBLISH NEW MESSAGE");
            return m_sentMessages[m_lastSentMessage++];
        }
        /// <summary>
		/// Removes a message from the message queue.
		/// </summary>
        public ServiceResult Acknowledge(OperationContext context, uint sequenceNumber)
        {
            lock (m_lock)
            {
                // check session.
                VerifySession(context);

                // clear lifetime counter.
                ResetLifetimeCount();

                // find message in queue.
                for (int ii = 0; ii < m_sentMessages.Count; ii++)
                {
                    if (m_sentMessages[ii].SequenceNumber == sequenceNumber)
                    {
                        if (m_lastSentMessage > ii)
                        {
                            m_lastSentMessage--;
                        }

                        m_sentMessages.RemoveAt(ii);
                        return null;
                    }
                }

                if (sequenceNumber == 0)
                {
                    return StatusCodes.BadSequenceNumberInvalid;
                }

                // TraceState("ACK " + sequenceNumber.ToString());

                // message not found.
                return StatusCodes.BadSequenceNumberUnknown;
            }
        }
        /// <summary>
        /// Throws an exception if the session is not the owner.
        /// </summary>
        private void VerifySession(OperationContext context)
        {
            if (m_expired)
            {
                throw new ServiceResultException(StatusCodes.BadSubscriptionIdInvalid);
            }

            if (!Object.ReferenceEquals(context.Session, m_session))
            {
                throw new ServiceResultException(StatusCodes.BadSessionIdInvalid, "Session no longer owns the subscription.");
            }
        }
        /// <summary>
        /// Verifies that a condition refresh operation is permitted.
        /// </summary>
        public void ValidateConditionRefresh(OperationContext context)
        {
            lock (m_lock)
            {  
                VerifySession(context);

                if (m_refreshInProgress)
                {
                    throw new ServiceResultException(StatusCodes.BadRefreshInProgress);
                }
            }
        }
Exemple #10
0
		/// <summary>
		/// Deletes the monitored items in a subscription.
		/// </summary>
		private void DeleteMonitoredItems(
			OperationContext             context,
            UInt32Collection             monitoredItemIds,
            bool                         doNotCheckSession,
            out StatusCodeCollection     results,
            out DiagnosticInfoCollection diagnosticInfos)
        {
            if (context == null)          throw new ArgumentNullException("context");
            if (monitoredItemIds == null) throw new ArgumentNullException("monitoredItemIds");

            int count = monitoredItemIds.Count;

            bool diagnosticsExist = false;
            results = new StatusCodeCollection(count);
            diagnosticInfos = null;

            if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
            {
                diagnosticInfos = new DiagnosticInfoCollection(count);
            }
            
            // build list of items to modify.
            List<IMonitoredItem> monitoredItems = new List<IMonitoredItem>(count);
            List<ServiceResult> errors = new List<ServiceResult>(count);
            double[] originalSamplingIntervals = new double[count];
            MonitoringMode[] originalMonitoringModes = new MonitoringMode[count];

            bool validItems = false;

            lock (m_lock)
            {
                // check session.
                if (!doNotCheckSession)
                {
                    VerifySession(context);
                }

                // clear lifetime counter.
                ResetLifetimeCount();
                
                for (int ii = 0; ii < count; ii++)
                {
                    LinkedListNode<IMonitoredItem> node = null;

                    if (!m_monitoredItems.TryGetValue(monitoredItemIds[ii], out node))
                    {
                        monitoredItems.Add(null);
                        errors.Add(StatusCodes.BadMonitoredItemIdInvalid);

                        // update diagnostics.
                        if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                        {
                            DiagnosticInfo diagnosticInfo = ServerUtils.CreateDiagnosticInfo(m_server, context, errors[ii]);
                            diagnosticsExist = true;
                            diagnosticInfos.Add(diagnosticInfo);
                        }

                        continue;
                    }
                    
                    IMonitoredItem monitoredItem = node.Value;
                    monitoredItems.Add(monitoredItem);

                    // remove the item from the internal lists.
                    m_monitoredItems.Remove(monitoredItemIds[ii]);
                    m_itemsToTrigger.Remove(monitoredItemIds[ii]);

                    //remove the links towards the deleted monitored item
                    List<ITriggeredMonitoredItem> triggeredItems = null;
                    foreach (KeyValuePair<uint, List<ITriggeredMonitoredItem>> item in m_itemsToTrigger)
                    {
                        triggeredItems = item.Value;
                        for (int jj = 0; jj < triggeredItems.Count; jj++)
                        {
                            if (triggeredItems[jj].Id == monitoredItemIds[ii])
                            {
                                triggeredItems.RemoveAt(jj);
                                break;
                            }
                        }
                    }
                    
                    if (node.List != null)
                    {
                        node.List.Remove(node);
                    }

                    originalSamplingIntervals[ii] = monitoredItem.SamplingInterval;
                    originalMonitoringModes[ii] = monitoredItem.MonitoringMode;

                    errors.Add(null);
                    validItems = true;

                    // update diagnostics.
                    if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                    {
                        diagnosticInfos.Add(null);
                    }
                }
            }
   
            // update items.
            if (validItems)
            {
                m_server.NodeManager.DeleteMonitoredItems(
                    context,
                    m_id,
                    monitoredItems,
                    errors);
            }
            
            lock (m_lock)
            {
                // update diagnostics.
                for (int ii = 0; ii < errors.Count; ii++)
                {
                    ServiceResult error = errors[ii];

                    if (error == null)
                    {
                        results.Add(StatusCodes.Good);
                    }
                    else
                    {
                        results.Add(error.StatusCode);
                    }

                    // update diagnostics.
                    if (ServiceResult.IsGood(error))
                    {
                        RemoveItemToSamplingInterval(originalSamplingIntervals[ii], originalMonitoringModes[ii]);
                    }

                    if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                    {
                        if (error != null && error.Code != StatusCodes.Good)
                        {
                            diagnosticInfos[ii] = ServerUtils.CreateDiagnosticInfo(m_server, context, error);
                            diagnosticsExist = true;
                        }
                    }
                }

                // clear diagnostics if not required.
                if (!diagnosticsExist && diagnosticInfos != null)
                {
                    diagnosticInfos.Clear();
                }

                // update diagnostics.
                lock (m_diagnostics)
                {
                    m_diagnostics.MonitoredItemCount = 0;
                    m_diagnostics.DisabledMonitoredItemCount = 0;
                }

                // TraceState("ITEMS DELETED");
            }
        }
Exemple #11
0
		/// <summary>
		/// Modifies monitored items in a subscription.
		/// </summary>
		public void ModifyMonitoredItems(
			OperationContext                        context,
			TimestampsToReturn                      timestampsToReturn,
			MonitoredItemModifyRequestCollection    itemsToModify,
			out MonitoredItemModifyResultCollection results,
            out DiagnosticInfoCollection            diagnosticInfos)
        {
            if (context == null)       throw new ArgumentNullException("context");
            if (itemsToModify == null) throw new ArgumentNullException("itemsToModify");

            int count = itemsToModify.Count;

            // allocate results.
            bool diagnosticsExist = false;
            results = new MonitoredItemModifyResultCollection(count);
            diagnosticInfos = null;
            
            if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
            {
                diagnosticInfos = new DiagnosticInfoCollection(count);
            }
            
            // build list of items to modify.
            List<IMonitoredItem> monitoredItems = new List<IMonitoredItem>(count);
            List<ServiceResult> errors = new List<ServiceResult>(count);
            List<MonitoringFilterResult> filterResults = new List<MonitoringFilterResult>(count);
            double[] originalSamplingIntervals = new double[count];

            bool validItems = false;

            lock (m_lock)
            {
                // check session.
                VerifySession(context);

                // clear lifetime counter.
                ResetLifetimeCount();

                for (int ii = 0; ii < count; ii++)
                {
                    filterResults.Add(null);

                    LinkedListNode<IMonitoredItem> node = null;

                    if (!m_monitoredItems.TryGetValue(itemsToModify[ii].MonitoredItemId, out node))
                    {
                        monitoredItems.Add(null);
                        errors.Add(StatusCodes.BadMonitoredItemIdInvalid);

                        // update diagnostics.
                        if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                        {
                            DiagnosticInfo diagnosticInfo = ServerUtils.CreateDiagnosticInfo(m_server, context, errors[ii]);
                            diagnosticsExist = true;
                            diagnosticInfos.Add(diagnosticInfo);
                        }

                        continue;
                    }
                    
                    IMonitoredItem monitoredItem = node.Value;
                    monitoredItems.Add(monitoredItem);
                    originalSamplingIntervals[ii] = monitoredItem.SamplingInterval;

                    errors.Add(null);
                    validItems = true;

                    // update diagnostics.
                    if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                    {
                        diagnosticInfos.Add(null);
                    }
                }
            }
                
             // update items.
            if (validItems)
            {
                m_server.NodeManager.ModifyMonitoredItems(
                    context,
                    timestampsToReturn,
                    monitoredItems,
                    itemsToModify,
                    errors,
                    filterResults);
            }
                   
            lock (m_lock)
            {             
                // create results.
                for (int ii = 0; ii < errors.Count; ii++)
                {
                    ServiceResult error = errors[ii];

                    MonitoredItemModifyResult result = null;

                    if (ServiceResult.IsGood(error))
                    {
                        error = monitoredItems[ii].GetModifyResult(out result);
                    }

                    if (result == null)
                    {
                        result = new MonitoredItemModifyResult();
                    }
                    
                    if (error == null)
                    {
                        result.StatusCode = StatusCodes.Good;
                    }
                    else
                    {
                        result.StatusCode = error.StatusCode;
                    }

                    // update diagnostics.
                    if (ServiceResult.IsGood(error))
                    {
                        ModifyItemSamplingInterval(originalSamplingIntervals[ii], result.RevisedSamplingInterval, monitoredItems[ii].MonitoringMode);
                    }

                    if (filterResults[ii] != null)
                    {
                        result.FilterResult = new ExtensionObject(filterResults[ii]);
                    }

                    results.Add(result);

                    if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                    {
                        if (error != null && error.Code != StatusCodes.Good)
                        {
                            diagnosticInfos[ii] = ServerUtils.CreateDiagnosticInfo(m_server, context, error);
                            diagnosticsExist = true;
                        }
                    }
                }

                // clear diagnostics if not required.
                if (!diagnosticsExist && diagnosticInfos != null)
                {
                    diagnosticInfos.Clear();
                }
                
                // TraceState("ITEMS MODIFIED");
            }
        }
        /// <summary>
        /// Activates an existing session
        /// </summary>
        public virtual bool ActivateSession(
            OperationContext context,
            NodeId authenticationToken,
            SignatureData clientSignature,
            List <SoftwareCertificate> clientSoftwareCertificates,
            ExtensionObject userIdentityToken,
            SignatureData userTokenSignature,
            StringCollection localeIds,
            out byte[] serverNonce)
        {
            serverNonce = null;

            Session           session         = null;
            UserIdentityToken newIdentity     = null;
            UserTokenPolicy   userTokenPolicy = null;

            lock (m_lock)
            {
                // find session.
                if (!m_sessions.TryGetValue(authenticationToken, out session))
                {
                    throw new ServiceResultException(StatusCodes.BadSessionClosed);
                }

                // create new server nonce.
                serverNonce = Utils.Nonce.CreateNonce((uint)m_minNonceLength);

                // validate before activation.
                session.ValidateBeforeActivate(
                    context,
                    clientSignature,
                    clientSoftwareCertificates,
                    userIdentityToken,
                    userTokenSignature,
                    localeIds,
                    serverNonce,
                    out newIdentity,
                    out userTokenPolicy);
            }

            IUserIdentity identity          = null;
            IUserIdentity effectiveIdentity = null;
            ServiceResult error             = null;

            try
            {
                // check if the application has a callback which validates the identity tokens.
                lock (m_eventLock)
                {
                    if (m_ImpersonateUser != null)
                    {
                        ImpersonateEventArgs args = new ImpersonateEventArgs(newIdentity, userTokenPolicy);
                        m_ImpersonateUser(session, args);

                        if (ServiceResult.IsBad(args.IdentityValidationError))
                        {
                            error = args.IdentityValidationError;
                        }
                        else
                        {
                            identity          = args.Identity;
                            effectiveIdentity = args.EffectiveIdentity;
                        }
                    }
                }

                // parse the token manually if the identity is not provided.
                if (identity == null)
                {
                    identity = new UserIdentity(newIdentity);
                }

                // use the identity as the effectiveIdentity if not provided.
                if (effectiveIdentity == null)
                {
                    effectiveIdentity = identity;
                }
            }
            catch (Exception e)
            {
                if (e is ServiceResultException)
                {
                    throw e;
                }

                throw ServiceResultException.Create(
                          StatusCodes.BadIdentityTokenInvalid,
                          e,
                          "Could not validate user identity token: {0}",
                          newIdentity);
            }

            // check for validation error.
            if (ServiceResult.IsBad(error))
            {
                throw new ServiceResultException(error);
            }

            // activate session.
            bool contextChanged = session.Activate(
                context,
                clientSoftwareCertificates,
                newIdentity,
                identity,
                effectiveIdentity,
                localeIds,
                serverNonce);

            // raise session related event.
            if (contextChanged)
            {
                RaiseSessionEvent(session, SessionEventReason.Activated);
            }

            // indicates that the identity context for the session has changed.
            return(contextChanged);
        }
 /// <summary>
 /// Refreshes the conditions for the specified subscription.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="subscriptionId">The subscription identifier.</param>
 public void ConditionRefresh(OperationContext context, uint subscriptionId)
 {
     m_subscriptionManager.ConditionRefresh(context, subscriptionId);
 }
 /// <summary>
 /// Closes the specified session.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="sessionId">The session identifier.</param>
 /// <param name="deleteSubscriptions">if set to <c>true</c> subscriptions are to be deleted.</param>
 public void CloseSession(OperationContext context, NodeId sessionId, bool deleteSubscriptions)
 {
     m_nodeManager.SessionClosing(context, sessionId, deleteSubscriptions);
     m_subscriptionManager.SessionClosing(context, sessionId, deleteSubscriptions);
     m_sessionManager.CloseSession(sessionId);
 }
Exemple #15
0
		/// <summary>
		/// Updates the publishing parameters for the subscription.
		/// </summary>
        public void Modify(
            OperationContext context,
            double           publishingInterval,
            uint             maxLifetimeCount,
            uint             maxKeepAliveCount,
            uint             maxNotificationsPerPublish,
            byte             priority)
        {
            lock (m_lock)
            {
                // check session.
                VerifySession(context);

                // clear lifetime counter.
                ResetLifetimeCount();

                m_maxLifetimeCount = maxLifetimeCount;

                // update publishing interval.
                if (publishingInterval != m_publishingInterval)
                {
                    m_publishingInterval = publishingInterval;
                    m_publishTimerExpiry = (HiResClock.UtcNow.Ticks/TimeSpan.TicksPerMillisecond) + (long)publishingInterval;
                    ResetKeepaliveCount();
                }
                
                // update keep alive count.
                if (maxKeepAliveCount != m_maxKeepAliveCount)
                {
                    m_maxKeepAliveCount = maxKeepAliveCount;
                }

                m_maxNotificationsPerPublish = maxNotificationsPerPublish;

                // update priority.
                m_priority = priority;

                // update diagnostics
                lock (m_diagnostics)
                {   
                    m_diagnostics.ModifyCount++;
                    m_diagnostics.PublishingInterval = m_publishingInterval;
                    m_diagnostics.MaxKeepAliveCount = m_maxKeepAliveCount;
                    m_diagnostics.MaxLifetimeCount = m_maxLifetimeCount;
                    m_diagnostics.Priority = m_priority;
                    m_diagnostics.MaxNotificationsPerPublish = m_maxNotificationsPerPublish;
                }
                
                // TraceState("MODIFIED");
            }
        }
		/// <summary>
		/// Publishes all available data change notifications.
		/// </summary>
		public virtual bool Publish(
            OperationContext                 context, 
            Queue<MonitoredItemNotification> notifications,
            Queue<DiagnosticInfo>            diagnostics)
		{
            if (context == null)       throw new ArgumentNullException("context");
            if (notifications == null) throw new ArgumentNullException("notifications");
            if (diagnostics == null)   throw new ArgumentNullException("diagnostics");
            
			lock (m_lock)
		    {
                // check if the item reports data changes.
                if ((m_typeMask & MonitoredItemTypeMask.DataChange) == 0)
                {
					return false;
                }

                // only publish if reporting.
                if (!IsReadyToPublish)
                {
                    return false;
                }

                // pull any unprocessed data.
                if (m_calculator != null)
                {
                    if (m_calculator.HasEndTimePassed(DateTime.UtcNow))
                    {
                        DataValue processedValue = m_calculator.GetProcessedValue(false);

                        while (processedValue != null)
                        {
                            AddValueToQueue(processedValue, null);
                        }

                        processedValue = m_calculator.GetProcessedValue(true);
                        AddValueToQueue(processedValue, null);
                    }
                }

                // go to the next sampling interval.
                IncrementSampleTime();
                
                // check if queueing enabled.
                if (m_queue != null)
                {
                    DataValue value = null;
                    ServiceResult error = null;

                    while (m_queue.Publish(out value, out error))
                    {
                        Publish(context, notifications, diagnostics, value, error);
                    }
                }

                // publish last value if no queuing.
                else
                {
                    Utils.Trace("DEQUEUE VALUE: Value={0} CODE={1}<{1:X8}> OVERFLOW={2}", m_lastValue.WrappedValue, m_lastValue.StatusCode.Code, m_lastValue.StatusCode.Overflow);
                    Publish(context, notifications, diagnostics, m_lastValue, m_lastError);
                }
                
				// reset state variables.
				m_overflow = false;
                m_readyToPublish = false;
                m_readyToTrigger = false;
                m_triggered = false;

                return false;
			}
		}
Exemple #17
0
        /// <summary>
        /// Does any processing before a transition occurs.
        /// </summary>
        protected virtual void OnBeforeTransition(OperationContext context, Transition transition, QualifiedName cause)
        {
            // raise a notification that a transition is about to occur.
            if (m_TransitionInitiated != null)
            {
                StateMachineTransitionEventArgs args = new StateMachineTransitionEventArgs(transition.FromState.BrowseName, transition.ToState.BrowseName, cause);
                
                m_TransitionInitiated(context, this, args);

                if (args.Cancel)
                {
                    throw ServiceResultException.Create(StatusCodes.Bad, "Transition to State '{0}' was cancelled because: '{1}'.", transition.ToState.DisplayName, args.CancelReason);
                }
            }
        }
Exemple #18
0
		/// <summary>
		/// Adds monitored items to a subscription.
		/// </summary>
		public void CreateMonitoredItems(
            OperationContext                        context,
            TimestampsToReturn                      timestampsToReturn,
            MonitoredItemCreateRequestCollection    itemsToCreate, 
            out MonitoredItemCreateResultCollection results, 
            out DiagnosticInfoCollection            diagnosticInfos)
        {
            if (context == null)       throw new ArgumentNullException("context");
            if (itemsToCreate == null) throw new ArgumentNullException("itemsToCreate");
            
            int count = itemsToCreate.Count;
            
            lock (m_lock)
            {
                // check session.
                VerifySession(context);

                // clear lifetime counter.
                ResetLifetimeCount();
            }
             
            // create the monitored items.
            List<IMonitoredItem> monitoredItems = new List<IMonitoredItem>(count);
            List<ServiceResult> errors = new List<ServiceResult>(count);
            List<MonitoringFilterResult> filterResults = new List<MonitoringFilterResult>(count);

            for (int ii = 0; ii < count; ii++)
            {
                monitoredItems.Add(null);
                errors.Add(null);
                filterResults.Add(null);
            }
            
            m_server.NodeManager.CreateMonitoredItems(
                context,
                this.m_id,
                m_publishingInterval,
                timestampsToReturn,
                itemsToCreate,
                errors,
                filterResults,
                monitoredItems);
                
            // allocate results.
            bool diagnosticsExist = false;
            results = new MonitoredItemCreateResultCollection(count);
            diagnosticInfos = null;

            if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
            {
                diagnosticInfos = new DiagnosticInfoCollection(count);
            }

            lock (m_lock)
            {
                // check session again after CreateMonitoredItems.
                VerifySession(context);

                for (int ii = 0; ii < errors.Count; ii++)
                {
                    // update results.
                    MonitoredItemCreateResult result = null;
                    
                    if (ServiceResult.IsBad(errors[ii]))
                    {
                        result = new MonitoredItemCreateResult();
                        result.StatusCode = errors[ii].Code;

                        if (filterResults[ii] != null)
                        {
                            result.FilterResult = new ExtensionObject(filterResults[ii]);
                        }
                    }
                    else
                    {
                        IMonitoredItem monitoredItem = monitoredItems[ii];

                        if (monitoredItem != null)
                        {
                            monitoredItem.SubscriptionCallback = this;
                            
                            LinkedListNode<IMonitoredItem> node = m_itemsToCheck.AddLast(monitoredItem);
                            m_monitoredItems.Add(monitoredItem.Id, node);

                            errors[ii] = monitoredItem.GetCreateResult(out result);

                            // update sampling interval diagnostics.
                            AddItemToSamplingInterval(result.RevisedSamplingInterval, itemsToCreate[ii].MonitoringMode);
                        }
                    }                   

                    results.Add(result);

                    // update diagnostics.
                    if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                    {
                        DiagnosticInfo diagnosticInfo = null;
                        
                        if (errors[ii] != null && errors[ii].Code != StatusCodes.Good)
                        {
                            diagnosticInfo = ServerUtils.CreateDiagnosticInfo(m_server, context, errors[ii]);
                            diagnosticsExist = true;
                        }

                        diagnosticInfos.Add(diagnosticInfo);
                    }
                }

                // clear diagnostics if not required.
                if (!diagnosticsExist && diagnosticInfos != null)
                {
                    diagnosticInfos.Clear();
                }

                // update diagnostics.
                lock (m_diagnostics)
                {
                    m_diagnostics.MonitoredItemCount = 0;
                    m_diagnostics.DisabledMonitoredItemCount = 0;
                }
                
                // TraceState("ITEMS CREATED");
            }
        }
Exemple #19
0
        /// <summary>
        /// Does any processing after a transition occurs.
        /// </summary>
        protected virtual void OnAfterTransition(OperationContext context, Transition transition, QualifiedName cause)
        {
            // raise a notification that a transition has occurred.
            if (m_TransitionCompleted != null)
            {
                StateMachineTransitionEventArgs args = new StateMachineTransitionEventArgs(
                    transition.FromState.BrowseName, 
                    transition.ToState.BrowseName, 
                    cause);

                m_TransitionCompleted(context, this, args);
            }
        }
Exemple #20
0
		/// <summary>
		/// Deletes the monitored items in a subscription.
		/// </summary>
        public void DeleteMonitoredItems(
            OperationContext context,
            UInt32Collection monitoredItemIds,
            out StatusCodeCollection results,
            out DiagnosticInfoCollection diagnosticInfos)
        {
            DeleteMonitoredItems(context, monitoredItemIds, false, out results, out diagnosticInfos);
        }
Exemple #21
0
        /// <summary>
        /// Ends a transition (reports events for all effects).
        /// </summary>
        protected virtual void EndTransition(OperationContext context, Transition transition, QualifiedName cause)
        {
            if (transition != null)
            {
                foreach (NodeId effectId in transition.Effects)
                {
                    // check if the effects are being surpressed.
                    if (m_suppressEffects)
                    {
                        m_unreportedEffect = true;
                        return;
                    }

                    ReportEffect(context, transition, cause, effectId);
                }
            }
        }
Exemple #22
0
		/// <summary>
		/// Changes the monitoring mode for a set of items.
		/// </summary>
        public void SetMonitoringMode(
            OperationContext             context,
            MonitoringMode               monitoringMode,
            UInt32Collection             monitoredItemIds,
            out StatusCodeCollection     results, 
            out DiagnosticInfoCollection diagnosticInfos)
        {  
            if (context == null)          throw new ArgumentNullException("context");
            if (monitoredItemIds == null) throw new ArgumentNullException("monitoredItemIds");

            int count = monitoredItemIds.Count;

            bool diagnosticsExist = false;
            results = new StatusCodeCollection(count);
            diagnosticInfos = null;

            if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
            {
                diagnosticInfos = new DiagnosticInfoCollection(count);
            }
        
            // build list of items to modify.
            List<IMonitoredItem> monitoredItems = new List<IMonitoredItem>(count);
            List<ServiceResult> errors = new List<ServiceResult>(count);
            MonitoringMode[] originalMonitoringModes = new MonitoringMode[count];

            bool validItems = false;

            lock (m_lock)
            {
                // check session.
                VerifySession(context);

                // clear lifetime counter.
                ResetLifetimeCount();

                for (int ii = 0; ii < count; ii++)
                {
                    LinkedListNode<IMonitoredItem> node = null;

                    if (!m_monitoredItems.TryGetValue(monitoredItemIds[ii], out node))
                    {
                        monitoredItems.Add(null);
                        errors.Add(StatusCodes.BadMonitoredItemIdInvalid);

                        // update diagnostics.
                        if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                        {
                            DiagnosticInfo diagnosticInfo = ServerUtils.CreateDiagnosticInfo(m_server, context, errors[ii]);
                            diagnosticsExist = true;
                            diagnosticInfos.Add(diagnosticInfo);
                        }

                        continue;
                    }
                    
                    IMonitoredItem monitoredItem = node.Value;
                    monitoredItems.Add(monitoredItem);
                    originalMonitoringModes[ii] = monitoredItem.MonitoringMode;

                    errors.Add(null);
                    validItems = true;

                    // update diagnostics.
                    if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                    {
                        diagnosticInfos.Add(null);
                    }
                }
            }

            // update items.
            if (validItems)
            {
                m_server.NodeManager.SetMonitoringMode(
                    context,
                    monitoringMode,
                    monitoredItems,
                    errors);
            }
                
            lock (m_lock)
            {
                // update diagnostics.
                for (int ii = 0; ii < errors.Count; ii++)
                {
                    ServiceResult error = errors[ii];

                    if (error == null)
                    {
                        results.Add(StatusCodes.Good);
                    }
                    else
                    {
                        results.Add(error.StatusCode);
                    }
                    
                    // update diagnostics.
                    if (ServiceResult.IsGood(error))
                    {
                        ModifyItemMonitoringMode(monitoredItems[ii].SamplingInterval, originalMonitoringModes[ii], monitoringMode);
                    }

                    if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                    {
                        if (error != null && error.Code != StatusCodes.Good)
                        {
                            diagnosticInfos[ii] = ServerUtils.CreateDiagnosticInfo(m_server, context, error);
                            diagnosticsExist = true;
                        }
                    }
                }

                // clear diagnostics if not required.
                if (!diagnosticsExist && diagnosticInfos != null)
                {
                    diagnosticInfos.Clear();
                }

                // update diagnostics.
                lock (m_diagnostics)
                {
                    m_diagnostics.MonitoredItemCount = 0;
                    m_diagnostics.DisabledMonitoredItemCount = 0;
                }

                if (monitoringMode == MonitoringMode.Disabled)
                {
                    // TraceState("ITEMS DISABLED");
                }
                else if (monitoringMode == MonitoringMode.Reporting)
                {
                    // TraceState("ITEMS REPORTING ENABLED");
                }
                else
                {
                    // TraceState("ITEMS SAMPLING ENABLED");
                }
            }
        }
Exemple #23
0
        /// <summary>
        /// Reports an effect which is an effect of a transition.
        /// </summary>
        protected virtual void ReportEffect(
            OperationContext context, 
            Transition       transition, 
            QualifiedName    cause,
            NodeId           effectId)
        {
            if (effectId == ObjectTypes.TransitionEventType)
            {
                TransitionEvent e = TransitionEvent.Construct(Server);

                e.InitializeNewEvent();
                
                e.Message.Value       = Utils.Format("StateMachine has moved to the {0} state.", transition.ToState.DisplayName);
                e.SourceNode.Value    = NodeId;
                e.SourceName.Value    = BrowseName.Name;
                e.Severity.Value      = 10;
                e.ReceiveTime.Value   = DateTime.UtcNow;
                e.FromState.Value     = transition.FromState.DisplayName;
                e.ToState.Value       = transition.ToState.DisplayName;

                ReportEvent(e);
            }
        }
Exemple #24
0
        /// <summary>
        /// Refreshes the conditions.
        /// </summary>
        public void ConditionRefresh()
        {
            ServerSystemContext systemContext = m_server.DefaultSystemContext.Copy(m_session);
            List<IEventMonitoredItem> monitoredItems = new List<IEventMonitoredItem>();

            lock (m_lock)
            {  
                // generate start event.
                RefreshStartEventState e = new RefreshStartEventState(null);
                            
                TranslationInfo message = new TranslationInfo(
                    "RefreshStartEvent",
                    "en-US",
                    "Condition refresh started for subscription {0}.",
                    m_id);

                e.Initialize(
                    systemContext,
                    null,
                    EventSeverity.Low,
                    new LocalizedText(message));
                
                e.SetChildValue(systemContext, BrowseNames.SourceNode, m_diagnosticsId, false);
                e.SetChildValue(systemContext, BrowseNames.SourceName, Utils.Format("Subscription/{0}", m_id), false);
                e.SetChildValue(systemContext, BrowseNames.ReceiveTime, DateTime.UtcNow, false);

                // build list of items to refresh.
                foreach (LinkedListNode<IMonitoredItem> monitoredItem in m_monitoredItems.Values)
                {
                    MonitoredItem eventMonitoredItem = monitoredItem.Value as MonitoredItem;

                    if (eventMonitoredItem.EventFilter != null)
                    {
                        // queue start refresh event.
                        eventMonitoredItem.QueueEvent(e, true);

                        // add to list that gets reported to the NodeManagers.
                        monitoredItems.Add(eventMonitoredItem);
                    }
                }

                // nothing to do if no event subscriptions.
                if (monitoredItems.Count == 0)
                {
                    return;
                }
            }
            
            // tell the NodeManagers to report the current state of the conditions.
            try
            {
                m_refreshInProgress = true;

                OperationContext operationContext = new OperationContext(m_session, DiagnosticsMasks.None);
                m_server.NodeManager.ConditionRefresh(operationContext, monitoredItems);
            }
            finally
            {
                m_refreshInProgress = false;
            }
            
            lock (m_lock)
            {  
                // generate start event.
                RefreshEndEventState e = new RefreshEndEventState(null);
                            
                TranslationInfo message = new TranslationInfo(
                    "RefreshEndEvent",
                    "en-US",
                    "Condition refresh completed for subscription {0}.",
                    m_id);

                e.Initialize(
                    systemContext,
                    null,
                    EventSeverity.Low,
                    new LocalizedText(message));
                
                e.SetChildValue(systemContext, BrowseNames.SourceNode, m_diagnosticsId, false);
                e.SetChildValue(systemContext, BrowseNames.SourceName, Utils.Format("Subscription/{0}", m_id), false);
                e.SetChildValue(systemContext, BrowseNames.ReceiveTime, DateTime.UtcNow, false);
                
                // send refresh end event.
                for (int ii = 0; ii < monitoredItems.Count; ii++)
                {
                    MonitoredItem monitoredItem = monitoredItems[ii] as MonitoredItem;

                    if (monitoredItem.EventFilter != null)
                    {
                        monitoredItem.QueueEvent(e, true);
                    }
                }
                    
                // TraceState("CONDITION REFRESH");
            }
        }
Exemple #25
0
        /// <summary>
        /// Reports an audit event for the cause.
        /// </summary>
        protected virtual void ReportAuditEvent(OperationContext context, Transition transition, QualifiedName cause, Exception exception)
        {
            AuditUpdateStateEvent e = CreateAuditEvent(context, transition, cause, exception);
                        
            e.InitializeNewEvent();
            
            e.Message.Value            = Utils.Format("Method {0} was called.", cause);
            e.SourceNode.Value         = NodeId;
            e.SourceName.Value         = "Method/Call";
            e.Severity.Value           = 1;
            e.ReceiveTime.Value        = DateTime.UtcNow;
            e.ActionTimeStamp.Value    = DateTime.UtcNow;
            e.OldStateId.Value         = m_currentStateName.StateNumber;
            e.NewStateId.Value         = m_currentStateName.StateNumber;  

            if (context != null)
            {
                e.ClientAuditEntryId.Value = context.AuditEntryId;
                e.ClientUserId.Value       = context.Session.Identity.DisplayName;
            }

            if (transition != null)
            {
                e.OldStateId.Value = transition.FromState.StateNumber;
                e.NewStateId.Value = transition.ToState.StateNumber;
            }

            ReportEvent(e);
        }
Exemple #26
0
		/// <summary>
		/// Deletes the subscription.
		/// </summary>
		public void Delete(OperationContext context)
        {
            // delete the diagnostics.
            if (m_diagnosticsId != null && !m_diagnosticsId.IsNullNodeId)
            {
                ServerSystemContext systemContext = m_server.DefaultSystemContext.Copy(m_session);
                m_server.DiagnosticsNodeManager.DeleteSubscriptionDiagnostics(systemContext, m_diagnosticsId);
            }

            lock (m_lock)
            {   
                try
                {        
                    // TraceState("DELETED");

                    // the context may be null if the server is cleaning up expired subscriptions.
                    // in this case we create a context with a dummy request and use the current session.
                    if (context == null)
                    {
                        RequestHeader requestHeader = new RequestHeader();
                        requestHeader.ReturnDiagnostics = (uint)(int)DiagnosticsMasks.OperationSymbolicIdAndText;
                        context = new OperationContext(requestHeader, RequestType.Unknown);
                    }

                    StatusCodeCollection results;
                    DiagnosticInfoCollection diagnosticInfos;

                    DeleteMonitoredItems(
                        context,
                        new UInt32Collection(m_monitoredItems.Keys),
                        true,
                        out results,
                        out diagnosticInfos);
                }
                catch (Exception e)
                {
                    Utils.Trace(e, "Delete items for subscription failed.");
                }
            }
        }
Exemple #27
0
 /// <summary>
 /// Creates an audit event for the cause.
 /// </summary>
 protected virtual AuditUpdateStateEvent CreateAuditEvent(
     OperationContext context, 
     Transition       transition, 
     QualifiedName    cause, 
     Exception        exception)
 {
     return AuditUpdateStateEvent.Construct(Server);
 }
Exemple #28
0
        /// <summary>
        /// Returns all available notifications.
        /// </summary>
        public NotificationMessage Publish(
            OperationContext      context, 
            out UInt32Collection  availableSequenceNumbers, 
            out bool              moreNotifications)
        {   
            if (context == null) throw new ArgumentNullException("context");
            
            NotificationMessage message = null;

            lock (m_lock)
            {
                moreNotifications = false;
                availableSequenceNumbers = null;

                // check if expired.
                if (m_expired)
                {
                    return null;
                }

                try
                {
                    // update diagnostics.
                    lock (m_diagnostics)
                    {
                        m_diagnostics.PublishRequestCount++;
                    }

                    message = InnerPublish(context, out availableSequenceNumbers, out moreNotifications);
                    
                    lock (m_diagnostics)
                    {
                        m_diagnostics.UnacknowledgedMessageCount = (uint)availableSequenceNumbers.Count;
                    }
                }
                finally
                {
                    // clear counters on success.
                    if (message != null)
                    {
                        // TraceState(Utils.Format("PUBLISH #{0}", message.SequenceNumber));
                        ResetKeepaliveCount();
                        m_waitingForPublish = moreNotifications;
                        ResetLifetimeCount();
                    }
                }
            }

            return message;
        }
        /// <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("context");
            if (subscriptionAcknowledgements == null) throw new ArgumentNullException("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();
                }
            }
        }
Exemple #30
0
        /// <summary>
        /// Returns a cached notification message.
        /// </summary>
        public NotificationMessage Republish(
            OperationContext context,
            uint             retransmitSequenceNumber)
        {            
            if (context == null) throw new ArgumentNullException("context");

            lock (m_diagnostics)
            {
                m_diagnostics.RepublishMessageRequestCount++;
            }

            lock (m_lock)
            {
                // check session.
                VerifySession(context);

                // clear lifetime counter.
                ResetLifetimeCount();
                
                lock (m_diagnostics)
                {
                    m_diagnostics.RepublishRequestCount++;
                    m_diagnostics.RepublishMessageRequestCount++;
                }

                // find message.
                foreach (NotificationMessage sentMessage in m_sentMessages)
                {
                    if (sentMessage.SequenceNumber == retransmitSequenceNumber)
                    {
                        lock (m_diagnostics)
                        {
                            m_diagnostics.RepublishMessageCount++;
                        }

                        return sentMessage;
                    }
                }

                // message not available.
                throw new ServiceResultException(StatusCodes.BadMessageNotAvailable);
            }
        }
Exemple #31
0
		/// <summary>
		/// Enables/disables publishing for the subscription.
		/// </summary>
		public void SetPublishingMode(
            OperationContext context,
			bool             publishingEnabled)
        {
            lock (m_lock)
            {
                // check session.
                VerifySession(context);

                // clear lifetime counter.
                ResetLifetimeCount();

                // update publishing interval.
                if (publishingEnabled != m_publishingEnabled)
                {
                    m_publishingEnabled = publishingEnabled;

                    // update diagnostics
                    lock (m_diagnostics)
                    {
                        m_diagnostics.PublishingEnabled = m_publishingEnabled;

                        if (m_publishingEnabled)
                        {
                            m_diagnostics.EnableCount++;
                        }
                        else
                        {
                            m_diagnostics.DisableCount++;
                        }
                    }
                }     
           
                // TraceState((publishingEnabled)?"ENABLED":"DISABLED");
            }
        }
		/// <summary>
		/// Publishes all available event notifications.
		/// </summary>
        public virtual bool Publish(OperationContext context, Queue<EventFieldList> notifications)
        {
            if (context == null)       throw new ArgumentNullException("context");
            if (notifications == null) throw new ArgumentNullException("notifications");

            lock (m_lock)
            {
                // check if the item reports events.
                if ((m_typeMask & MonitoredItemTypeMask.Events) == 0)
                {
					return false;
                }

                // only publish if reporting.
                if (!IsReadyToPublish)
                {
                    return false;
                }

                // go to the next sampling interval.
                IncrementSampleTime();

                // publish events.
                if (m_events != null)
                {
                    Utils.Trace("MONITORED ITEM: Publish(QueueSize={0})", notifications.Count);

                    EventFieldList overflowEvent = null;

                    if (m_overflow)
                    {
                        // construct event.
                        EventQueueOverflowEventState e = new EventQueueOverflowEventState(null);
                                
                        TranslationInfo message = new TranslationInfo(
                            "EventQueueOverflowEventState",
                            "en-US",
                            "Events lost due to queue overflow.");

                        ISystemContext systemContext = new ServerSystemContext(m_server, context);

                        e.Initialize(
                            systemContext,
                            null,
                            EventSeverity.Low,
                            new LocalizedText(message));

                        e.SetChildValue(systemContext, BrowseNames.SourceNode, ObjectIds.Server, false);
                        e.SetChildValue(systemContext, BrowseNames.SourceName, "Internal", false);

                        // fetch the event fields.
                        overflowEvent = GetEventFields(
                            new FilterContext(m_server.NamespaceUris, m_server.TypeTree, m_session.PreferredLocales),
                            m_filterToUse as EventFilter,
                            e);
                    }

                    // place event at the beginning of the queue.
                    if (overflowEvent != null && m_discardOldest)
                    {
                        notifications.Enqueue(overflowEvent);
                    }

                    for (int ii = 0; ii < m_events.Count; ii++)
                    {
                        EventFieldList fields = (EventFieldList)m_events[ii];

                        // apply any diagnostic masks.
                        for (int jj = 0; jj < fields.EventFields.Count; jj++)
                        {
                            object value = fields.EventFields[jj].Value;

                            StatusResult result = value as StatusResult;

                            if (result != null)
                            {
                                result.ApplyDiagnosticMasks(context.DiagnosticsMask, context.StringTable);
                            }
                        }

                        notifications.Enqueue((EventFieldList)m_events[ii]);
                    }

                    m_events.Clear();

                    // place event at the end of the queue.
                    if (overflowEvent != null && !m_discardOldest)
                    {
                        notifications.Enqueue(overflowEvent);
                    }

                    Utils.Trace("MONITORED ITEM: Publish(QueueSize={0})", notifications.Count);
                }

				// reset state variables.
				m_overflow = false;
                m_readyToPublish = false;
                m_readyToTrigger = false;
                m_triggered = false;

                return false;
            }
        }
Exemple #33
0
        /// <summary>
        /// Updates the triggers for the monitored item.
        /// </summary>
        public void SetTriggering(
            OperationContext context,
            uint triggeringItemId,
            UInt32Collection linksToAdd,
            UInt32Collection linksToRemove,
            out StatusCodeCollection addResults,
            out DiagnosticInfoCollection addDiagnosticInfos,
            out StatusCodeCollection removeResults,
            out DiagnosticInfoCollection removeDiagnosticInfos)
        {
            if (context == null) throw new ArgumentNullException("context");
            if (linksToAdd == null) throw new ArgumentNullException("linksToAdd");
            if (linksToRemove == null) throw new ArgumentNullException("linksToRemove");

            // allocate results.
            bool diagnosticsExist = false;
            addResults = new StatusCodeCollection();
            addDiagnosticInfos = null;
            removeResults = new StatusCodeCollection();
            removeDiagnosticInfos = null;

            if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
            {
                addDiagnosticInfos = new DiagnosticInfoCollection();
                removeDiagnosticInfos = new DiagnosticInfoCollection();
            }

            // build list of items to modify.
            lock (m_lock)
            {
                // check session.
                VerifySession(context);

                // clear lifetime counter.
                ResetLifetimeCount();

                // look up triggering item.
                LinkedListNode<IMonitoredItem> triggerNode = null;

                if (!m_monitoredItems.TryGetValue(triggeringItemId, out triggerNode))
                {
                    throw new ServiceResultException(StatusCodes.BadMonitoredItemIdInvalid);
                }

                // lookup existing list.
                List<ITriggeredMonitoredItem> triggeredItems = null;

                if (!m_itemsToTrigger.TryGetValue(triggeringItemId, out triggeredItems))
                {
                    m_itemsToTrigger[triggeringItemId] = triggeredItems = new List<ITriggeredMonitoredItem>();
                }

                // remove old links.
                for (int ii = 0; ii < linksToRemove.Count; ii++)
                {
                    removeResults.Add(StatusCodes.Good);

                    bool found = false;

                    for (int jj = 0; jj < triggeredItems.Count; jj++)
                    {
                        if (triggeredItems[jj].Id == linksToRemove[ii])
                        {
                            found = true;
                            triggeredItems.RemoveAt(jj);
                            break;
                        }
                    }

                    if (!found)
                    {
                        removeResults[ii] = StatusCodes.BadMonitoredItemIdInvalid;

                        // update diagnostics.
                        if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                        {
                            DiagnosticInfo diagnosticInfo = ServerUtils.CreateDiagnosticInfo(m_server, context, removeResults[ii]);
                            diagnosticsExist = true;
                            removeDiagnosticInfos.Add(diagnosticInfo);
                        }

                        continue;
                    }

                    // update diagnostics.
                    if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                    {
                        removeDiagnosticInfos.Add(null);
                    }
                }

                // add new links.
                for (int ii = 0; ii < linksToAdd.Count; ii++)
                {
                    addResults.Add(StatusCodes.Good);

                    LinkedListNode<IMonitoredItem> node = null;

                    if (!m_monitoredItems.TryGetValue(linksToAdd[ii], out node))
                    {
                        addResults[ii] = StatusCodes.BadMonitoredItemIdInvalid;

                        // update diagnostics.
                        if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                        {
                            DiagnosticInfo diagnosticInfo = ServerUtils.CreateDiagnosticInfo(m_server, context, addResults[ii]);
                            diagnosticsExist = true;
                            addDiagnosticInfos.Add(diagnosticInfo);
                        }

                        continue;
                    }

                    // check if triggering interface is supported.
                    ITriggeredMonitoredItem triggeredItem = node.Value as ITriggeredMonitoredItem;

                    if (triggeredItem == null)
                    {
                        addResults[ii] = StatusCodes.BadNotSupported;

                        // update diagnostics.
                        if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                        {
                            DiagnosticInfo diagnosticInfo = ServerUtils.CreateDiagnosticInfo(m_server, context, addResults[ii]);
                            diagnosticsExist = true;
                            addDiagnosticInfos.Add(diagnosticInfo);
                        }

                        continue;
                    }

                    // add value if not already in list.
                    bool found = false;

                    for (int jj = 0; jj < triggeredItems.Count; jj++)
                    {
                        if (triggeredItems[jj].Id == triggeredItem.Id)
                        {
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        triggeredItems.Add(triggeredItem);
                    }

                    // update diagnostics.
                    if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
                    {
                        addDiagnosticInfos.Add(null);
                    }
                }

                // remove an empty list.
                if (triggeredItems.Count == 0)
                {
                    m_itemsToTrigger.Remove(triggeringItemId);
                }

                // clear diagnostics if not required.
                if (!diagnosticsExist)
                {
                    if (addDiagnosticInfos != null) addDiagnosticInfos.Clear();
                    if (removeDiagnosticInfos != null) removeDiagnosticInfos.Clear();
                }
            }
        }
		/// <summary>
		/// Publishes a single data change notifications.
		/// </summary>
        protected virtual bool Publish(
            OperationContext                 context,
            Queue<MonitoredItemNotification> notifications,
            Queue<DiagnosticInfo>            diagnostics,
            DataValue                        value, 
            ServiceResult                    error)
        {            
            // 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;
            }

            ServerUtils.ReportPublishValue(m_nodeId, m_id, item.Value);
            notifications.Enqueue(item);

            // update diagnostic info.
            DiagnosticInfo diagnosticInfo = null;
            
            if ((m_diagnosticsMasks & DiagnosticsMasks.OperationAll) != 0)
            {
                diagnosticInfo = ServerUtils.CreateDiagnosticInfo(m_server, context, error);
            }

            diagnostics.Enqueue(diagnosticInfo);

            return false;
        }
        /// <summary>
        /// Creates a new session.
        /// </summary>
        public virtual Session CreateSession(
            OperationContext context,
            X509Certificate2 serverCertificate,
            string sessionName,
            byte[] clientNonce,
            ApplicationDescription clientDescription,
            string endpointUrl,
            X509Certificate2 clientCertificate,
            double requestedSessionTimeout,
            uint maxResponseMessageSize,
            out NodeId sessionId,
            out NodeId authenticationToken,
            out byte[] serverNonce,
            out double revisedSessionTimeout)
        {
            sessionId             = 0;
            revisedSessionTimeout = requestedSessionTimeout;

            Session session = null;

            lock (m_lock)
            {
                // check session count.
                if (m_maxSessionCount > 0 && m_sessions.Count >= m_maxSessionCount)
                {
                    throw new ServiceResultException(StatusCodes.BadTooManySessions);
                }

                // check for same Nonce in another session
                if (clientNonce != null)
                {
                    foreach (Session sessionIterator in m_sessions.Values)
                    {
                        if (Utils.CompareNonce(sessionIterator.ClientNonce, clientNonce))
                        {
                            throw new ServiceResultException(StatusCodes.BadNonceInvalid);
                        }
                    }
                }
                // can assign a simple identifier if secured.
                authenticationToken = null;

                if (!String.IsNullOrEmpty(context.ChannelContext.SecureChannelId))
                {
                    if (context.ChannelContext.EndpointDescription.SecurityMode != MessageSecurityMode.None)
                    {
                        authenticationToken = Utils.IncrementIdentifier(ref m_lastSessionId);
                    }
                }

                // must assign a hard-to-guess id if not secured.
                if (authenticationToken == null)
                {
                    byte[] token = Utils.Nonce.CreateNonce(32);
                    authenticationToken = new NodeId(token);
                }

                // determine session timeout.
                if (requestedSessionTimeout > m_maxSessionTimeout)
                {
                    revisedSessionTimeout = m_maxSessionTimeout;
                }

                if (requestedSessionTimeout < m_minSessionTimeout)
                {
                    revisedSessionTimeout = m_minSessionTimeout;
                }

                // create server nonce.
                serverNonce = Utils.Nonce.CreateNonce((uint)m_minNonceLength);

                // assign client name.
                if (String.IsNullOrEmpty(sessionName))
                {
                    sessionName = Utils.Format("Session {0}", sessionId);
                }

                // create instance of session.
                session = CreateSession(
                    context,
                    m_server,
                    serverCertificate,
                    authenticationToken,
                    clientNonce,
                    serverNonce,
                    sessionName,
                    clientDescription,
                    endpointUrl,
                    clientCertificate,
                    revisedSessionTimeout,
                    maxResponseMessageSize,
                    m_maxRequestAge,
                    m_maxBrowseContinuationPoints);

                // get the session id.
                sessionId = session.Id;

                // save session.
                m_sessions.Add(authenticationToken, session);
            }

            // raise session related event.
            RaiseSessionEvent(session, SessionEventReason.Created);

            // return session.
            return(session);
        }