The state table formally describes the operation of the Subscription. The following model of operations is described by this state table. This description applies when publishing is enabled or disabled for the Subscription.
After creation of the Subscription, the Serverstarts the publishing timer and restarts it whenever it expires. If the timer expires the number of times defined for the Subscriptionlifetime without having received a Subscription Servicerequest from the Client, the Subscriptionassumes that the Clientis no longer present, and terminates.
Clientssend Publishrequests to Serversto receive Notifications. Publishrequests are not directed to any one Subscriptionand, therefore, may be used by any Subscription. Each contains acknowledgements for one or more Subscriptions. These acknowledgements are processed when the Publishrequest is received. The Serverthen queues the request in a queue shared by all Subscriptions, except in the following cases.
- The previous Publishresponse indicated that there were still more Notificationsready to be transferred and there were no more Publishrequests queued to transfer them.
- The publishing timer of a Subscriptionexpired and there were either Notificationsto be sent or a keep-alive Messageto be sent.
In these cases, the newly received Publishrequest is processed immediately by the first Subscriptionto encounter either case (a) or case (b).
Each time the publishing timer expires, it is immediately reset. If there are Notificationsor a keep-alive Messageto be sent, it de-queues and processes a Publishrequest. When a Subscriptionprocesses a Publishrequest, it accesses the queues of its MonitoredItemsand de-queues its Notifications, if any. It returns these Notificationsin the response, setting the moreNotificationsflag if it was not able to return all available Notificationsin the response.
If there were Notificationsor a keep-alive Messageto be sent but there were no Publishrequests queued, the Subscriptionassumes that the Publishrequest is late and waits for the next Publishrequest to be received, as described in case (b).
If the Subscriptionis disabled when the publishing timer expires or if there are no Notificationsavailable, it enters the keep-alive state and sets the keep-alive counter to its maximum value as defined for the Subscription.
While in the keep-alive state, it checks for Notificationseach time the publishing timer expires. If one or more Notificationshave been generated, a Publishrequest is de-queued and a NotificationMessageis returned in the response. However, if the publishing timer expires without a Notificationbecoming available, a Publishrequest is de-queued and a keep-alive Messageis returned in the response. The Subscriptionthen returns to the normal state of waiting for the publishing timer to expire again. If, in either of these cases, there are no Publishrequests queued, the Subscriptionwaits for the next Publishrequest to be received, as described in case (b).
The Subscriptionstates are defined in Table 84.
State |
Description |
CLOSED |
The Subscriptionhas not yet been created or has terminated. |
CREATING |
The Subscriptionis being created. |
NORMAL |
The Subscriptionis cyclically checking for Notificationsfrom its MonitoredItems. The keep-alive counter is not used in this state. |
LATE |
The publishing timer has expired and there are Notificationsavailable or a keep-alive Messageis ready to be sent, but there are no Publishrequests queued. When in this state, the next Publishrequest is processed when it is received. The keep-alive counter is not used in this state. |
KEEPALIVE |
The Subscriptionis cyclically checking for Notificationsfrom its MonitoredItemsor for the keep-alive counter to count down to 0 from its maximum. |
The state table is described in Table 85. The following rules and conventions apply.
- Eventsrepresent the receipt of Servicerequests and the occurrence internal Events, such as timer expirations.
- Servicerequests Eventsmay be accompanied by conditions that test Serviceparameter values. Parameter names begin with a lower case letter.
- Internal Eventsmay be accompanied by conditions that test state Variablevalues. State Variablesare defined in 5.13.1.3. They begin with an upper case letter.
- Servicerequest and internal Eventsmay be accompanied by conditions represented by functions whose return value is tested. Functions are identified by “()” after their name. They are described in 5.13.1.4.
- When an Eventis received, the first transition for the current state is located and the transitions are searched sequentially for the first transition that meets the Eventor conditions criteria. If none are found, the Eventis ignored.
- Actions are described by functions and state Variablemanipulations.
- The LifetimeTimerExpires Eventis triggered when its corresponding counter reaches zero.
Table 85– Subscription State Table
# |
Current State |
Event/Conditions |
Action |
Next State |
1 |
CLOSED |
Receive CreateSubscription Request |
CreateSubscription() |
CREATING |
2 |
CREATING |
CreateSubscription fails |
ReturnNegativeResponse() |
CLOSED |
3 |
CREATING |
CreateSubscription succeeds |
InitializeSubscription() MessageSent = FALSE ReturnResponse() |
NORMAL |
4 |
NORMAL |
Receive PublishRequest && ( PublishingEnabled == FALSE || (PublishingEnabled == TRUE && MoreNotifications == FALSE) ) |
DeleteAckedNotificationMsgs() EnqueuePublishingReq() |
NORMAL |
5 |
NORMAL |
Receive PublishRequest && PublishingEnabled == TRUE && MoreNotifications == TRUE |
ResetLifetimeCounter() DeleteAckedNotificationMsgs() ReturnNotifications() MessageSent = TRUE |
NORMAL |
6 |
NORMAL |
PublishingTimer Expires && PublishingReqQueued == TRUE && PublishingEnabled == TRUE && NotificationsAvailable == TRUE |
ResetLifetimeCounter() StartPublishingTimer() DequeuePublishReq() ReturnNotifications() MessageSent == TRUE |
NORMAL |
7 |
NORMAL |
PublishingTimer Expires && PublishingReqQueued == TRUE && MessageSent == FALSE && ( PublishingEnabled == FALSE || (PublishingEnabled == TRUE && NotificationsAvailable == FALSE) ) |
ResetLifetimeCounter() StartPublishingTimer() DequeuePublishReq() ReturnKeepAlive() MessageSent == TRUE |
NORMAL |
8 |
NORMAL |
PublishingTimer Expires && PublishingReqQueued == FALSE && ( MessageSent == FALSE || (PublishingEnabled == TRUE && NotificationsAvailable == TRUE) ) |
StartPublishingTimer() |
LATE |
9 |
NORMAL |
PublishingTimer Expires && MessageSent == TRUE && ( PublishingEnabled == FALSE || (PublishingEnabled == TRUE && NotificationsAvailable == FALSE) ) |
StartPublishingTimer() ResetKeepAliveCounter() KeepAliveCounter-- |
KEEPALIVE |
10 |
LATE |
Receive PublishRequest && PublishingEnabled == TRUE && (NotificationsAvailable == TRUE || MoreNotifications == TRUE) |
ResetLifetimeCounter() DeleteAckedNotificationMsgs() ReturnNotifications() MessageSent = TRUE |
NORMAL |
11 |
LATE |
Receive PublishRequest && ( PublishingEnabled == FALSE || (PublishingEnabled == TRUE && NotificationsAvailable == FALSE && MoreNotifications == FALSE) ) |
ResetLifetimeCounter() DeleteAckedNotificationMsgs() ReturnKeepAlive() MessageSent = TRUE |
KEEPALIVE |
12 |
LATE |
PublishingTimer Expires |
StartPublishingTimer() |
LATE |
13 |
KEEPALIVE |
Receive PublishRequest |
DeleteAckedNotificationMsgs() EnqueuePublishingReq() |
KEEPALIVE |
14 |
KEEPALIVE |
PublishingTimer Expires && PublishingEnabled == TRUE && NotificationsAvailable == TRUE && PublishingReqQueued == TRUE |
ResetLifetimeCounter() StartPublishingTimer() DequeuePublishReq() ReturnNotifications() MessageSent == TRUE |
NORMAL |
15 |
KEEPALIVE |
PublishingTimer Expires && PublishingReqQueued == TRUE && KeepAliveCounter <= 1 && ( PublishingEnabled == FALSE || (PublishingEnabled == TRUE && NotificationsAvailable == FALSE ) |
StartPublishingTimer() DequeuePublishReq() ReturnKeepAlive() ResetKeepAliveCounter() |
KEEPALIVE |
16 |
KEEPALIVE |
PublishingTimer Expires && KeepAliveCounter > 1 && ( PublishingEnabled == FALSE || (PublishingEnabled == TRUE && NotificationsAvailable == FALSE) ) |
StartPublishingTimer() KeepAliveCounter-- |
KEEPALIVE |
17 |
KEEPALIVE |
PublishingTimer Expires && PublishingReqQueued == FALSE && ( KeepAliveCounter == 1 || (KeepAliveCounter > 1 && PublishingEnabled == TRUE && NotificationsAvailable == TRUE) ) |
StartPublishingTimer() |
LATE |
18 |
NORMAL || LATE || KEEPALIVE |
Receive ModifySubscription Request |
ResetLifetimeCounter() UpdateSubscriptionParams() ReturnResponse() |
SAME |
19 |
NORMAL || LATE || KEEPALIVE |
Receive SetPublishingMode Request |
ResetLifetimeCounter() SetPublishingEnabled() MoreNotifications = FALSE ReturnResponse() |
SAME |
20 |
NORMAL || LATE || KEEPALIVE |
Receive Republish Request && RequestedMessageFound == TRUE |
ResetLifetimeCounter() ReturnResponse() |
SAME |
21 |
NORMAL || LATE || KEEPALIVE |
Receive Republish Request && RequestedMessageFound == FALSE |
ResetLifetimeCounter() ReturnNegativeResponse() |
SAME |
22 |
NORMAL || LATE || KEEPALIVE |
Receive TransferSubscriptions Request && SessionChanged() == FALSE |
ResetLifetimeCounter() ReturnNegativeResponse () |
SAME |
23 |
NORMAL || LATE || KEEPALIVE |
Receive TransferSubscriptions Request && SessionChanged() == TRUE && ClientValidated() ==TRUE |
SetSession() ResetLifetimeCounter() ReturnResponse() IssueStatusChangeNotification() |
SAME |
24 |
NORMAL || LATE || KEEPALIVE |
Receive TransferSubscriptions Request && SessionChanged() == TRUE && ClientValidated() == FALSE |
ReturnNegativeResponse() |
SAME |
25 |
NORMAL || LATE || KEEPALIVE |
Receive DeleteSubscriptions Request && SubscriptionAssignedToClient ==TRUE |
DeleteMonitoredItems() DeleteClientPublReqQueue() |
CLOSED |
26 |
NORMAL || LATE || KEEPALIVE |
Receive DeleteSubscriptions Request && SubscriptionAssignedToClient ==FALSE |
ResetLifetimeCounter() ReturnNegativeResponse() |
SAME |
27 |
NORMAL || LATE || KEEPALIVE |
LifetimeCounter == 1 The LifetimeCounter is decremented if PublishingTimer expires and PublishingReqQueued == FALSE The LifetimeCounter is reset if PublishingReqQueued == TRUE. |
DeleteMonitoredItems() IssueStatusChangeNotification() |
CLOSED |