.NET Based OPC UA Client/Server SDK  3.4.2.542
SDK Layer

Overview

Every instance of a UA server has exactly one instance of the ServerManager object. This class is connected with the stack and is the first point of contact for all requests sent by Client applications. When a request arrives, it is validated and dispatched by this object. The handling of a request depends on the service; however, there are two possible design patterns.

If a service does not have a list of operations (CreateSession, CreateSubscription) or if the service is not expected to block on I/O (AddNodes, AddReferences), then the synchronous design pattern is used. In this case a method on the ServerManager is called from a stack thread pool thread and it blocks until processing completes. The response is returned when this method completes. If an exception occurs, the stack will catch it and return a ServiceFault using the information in the exception. The following figure illustrates the synchronous design pattern:

serversdkov_serverman_overview.png

If a service does have a list of operations (Read, Write, Call) and processing could take a lot of time, then the asynchronous design pattern is used. In this case, the begin method is called by the stack thread pool which calls a begin method for each operation. At this point the begin method exits and the thread is released back to the pool. As each operation completes, the thread executing the operation calls the complete method on the ServerManager and the result list is updated. When all operations have been processed, then the response is constructed and returned to the client. The response is sent using the last thread to call the complete method. If the implementer of the logic used to process the operation does not want this thread to be used to send the response, the implementer can tell the SDK to return the response using a stack thread pool thread. The following figure illustrates the asynchronous design pattern:

serversdkov_serverman_overview2.png

Manager Interfaces

The ServerManager uses the SDK API manager interfaces to implement services which operate on Nodes. Each Node belongs to exactly one NodeManager which implements the INodeManager interface. The ServerManager requests the appropriate manager interface for a Node by requesting the handle for the Node via the INodeManager.

A manager interface provides the following methods:

BeginTransaction
Starts a transaction. A manager may choose to process multiple operations in a single batch and this method allows the manager to initialize the batch. This method does nothing if the manager does not need to batch operations.
Begin<Operation>
Starts processing the operation. A manager may simply add the operation to the transaction created with BeginTransaction or it may do all of the processing required and call the Complete method for the operation.
FinishTransaction
Finishes a transaction. This tells the manager that the all operations have been added and the manager can process the transaction. This method does nothing if the manager processes operations immediately.

The transaction allows the implementer to group operations within a single request. This allows the implementer to optimize I/O by minimizing the requests made to an underlying system. A manager that operates on in-memory nodes would not need transactions and can complete the operation in the Begin<Operation> method. (Completing the operation means the Complete<Operation> callback is called before the Begin<Operation> method returns. The ServerManager is designed to expect that some managers will do this).

When the ServerManager calls the Begin<Operation> method, it passes the OperationHandle which wraps the handle returned from the NodeManager. The manager interface implementation must pass this handle in the Complete<Operation> callback when processing completes.

The following table lists the OPC UA services and which SDK API manager interface is used:

Service Name Manager Interface
FindServers
GetEndpoints
CreateSession
ActivateSession
CloseSession
Cancel
Browse INodeManager
BrowseNext INodeManager
TranslateBrowsePathToNodeIds INodeManager
RegisterNodes
UnregisterNodes
Read IIOManager
Write IIOManager
HistoryRead (Data) IHistoryReadDataManager
HistoryUpdate (Data) IHistoryUpdateDataManager
HistoryRead (Events) IHistoryReadEventManager
HistoryUpdate (Events) IHistoryUpdateEventManager
Call IMethodManager
CreateSubscription
ModifySubscription
DeleteSubscriptions
SetPublishingMode
Publish
Republish
TransferSubscription
CreateMonitoredItems IIOManager, IEventManager
ModifyMonitoredItems IIOManager, IEventManager
DeleteMonitoredItems IIOManager, IEventManager
SetMonitoringMode IIOManager, IEventManager
SetTriggering

If no manager interface is specified for a service, then the SDK handles all of the processing for the service.

NodeManagers, the RootNodeManager and the BaseNodeManager

A NodeManager manages a subset of the Nodes in the Server address space. The NodeManager registers the NamespaceUris of the Nodes it manages with the RootNodeManager which will assign a NamespaceIndex to the NamespaceUri. When the ServerManager needs to find a handle for a Node, it calls the RootNodeManager which uses the NamespaceIndex to look up the NodeManager which then provides the handle to the ServerManager. The assignment of a NamespaceUri to a NodeManager can happen at any time. If a NamespaceUri is already assigned, then the new NodeManager replaces the existing NodeManager.

The BaseNodeManager is a standard implementation for a NodeManager which relies on Nodes stored in the memory. It provides various methods that can be overridden to provide application specific behavior (see the section below for a more detailed explanation). The CoreNodeManager is a subtype of the BaseNodeManager which handles all of the Nodes defined in the specification. It includes logic to manage Nodes required for the diagnostic information defined in Part 5. A User can also use the Node management methods on the CoreNodeManager to add in memory Nodes to NamespaceIndex 1.

SessionManager and Session

The SessionManager is responsible for managing the active Sessions. The Session maintains the state of the Session created by a client. If a Client disappears, the Session and all resources allocated will be freed by the SessionManager after a timeout period expires.

The Session object also keeps track of the diagnostics information associated with the Session.

Any handles used for registered Nodes are also stored in the Session object and are discarded when the Session is closed.

SubscriptionManager, Subscriptions and MonitoredItems

The SubscriptionManager is responsible for managing all of active Subscriptions and maintaining a queue of Publish requests for each active Session. If a Session disappears, the SubscriptionManager will close the Subscriptions belonging to the Session unless they have been transferred to another Session with the TransferSubscriptions service.

The Subscription maintains a list of MonitoredItems. When these MonitoredItems have data or events ready to publish, it pulls data/events off the MonitoredItem queue and constructs a NotificationMessage which can be sent back to the client as a part of a Publish response.

The publishing cycle is triggered by a dedicated thread that checks for data to publish every 100 ms (the default, it can be changed with the PublishingIntervalResolution setting in the configuration file). Subscriptions that have data to be published will be called back with a thread from Stack Thread Pool when a Publish request is available for the Session.

The MonitoredItem class maintains a queue for events or data. It is responsible for applying any monitoring filter which is not applied by the source of the data or events. When a MonitoredItem is created the IIOManager or IEventManager is given a callback to use when data changes or events occur. The MonitoredItem also ensures the sampling rate is honored so sources of data can push data into the MonitoredItem at faster rates (source may need to do this if many MonitoredItems are requesting the same data that is only sampled once).

ServerInternalClient

The ServerInternalClient is a class that provides all for the basic UA services such as Read, Write, Call and Subscribe to clients within the process. These services are useful when NodeManagers need to get information from other NodeManagers. This could also be used to implement a historian that collects data from real time data managed by other NodeManagers.