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.

  1. The previous Publishresponse indicated that there were still more Notificationsready to be transferred and there were no more Publishrequests queued to transfer them.
  2. 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.

Table 84– Subscription States

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.

  1. Eventsrepresent the receipt of Servicerequests and the occurrence internal Events, such as timer expirations.
  2. Servicerequests Eventsmay be accompanied by conditions that test Serviceparameter values. Parameter names begin with a lower case letter.
  3. 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.
  4. 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.
  5. 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.
  6. Actions are described by functions and state Variablemanipulations.
  7. 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