|
@@ -92,12 +92,12 @@ void UA_MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *monitoredItem)
|
|
|
|
|
|
UA_StatusCode
|
|
|
MonitoredItem_ensureQueueSpace(UA_Server *server, UA_MonitoredItem *mon) {
|
|
|
- if(mon->queueSize <= mon->maxQueueSize)
|
|
|
+ if(mon->queueSize - mon->eventOverflows <= mon->maxQueueSize)
|
|
|
return UA_STATUSCODE_GOOD;
|
|
|
|
|
|
/* Remove notifications until the queue size is reached */
|
|
|
UA_Subscription *sub = mon->subscription;
|
|
|
- while(mon->queueSize > mon->maxQueueSize) {
|
|
|
+ while(mon->queueSize - mon->eventOverflows > mon->maxQueueSize) {
|
|
|
UA_assert(mon->queueSize >= 2); /* At least two Notifications in the queue */
|
|
|
|
|
|
/* Make sure that the MonitoredItem does not lose its place in the
|
|
@@ -128,46 +128,66 @@ MonitoredItem_ensureQueueSpace(UA_Server *server, UA_MonitoredItem *mon) {
|
|
|
|
|
|
#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
|
|
|
/* Create an overflow notification */
|
|
|
- /* if(mon->monitoredItemType == UA_MONITOREDITEMTYPE_EVENTNOTIFY) { */
|
|
|
- /* /\* EventFilterResult currently isn't being used */
|
|
|
- /* UA_EventFilterResult_deleteMembers(&del->data.event->result); *\/ */
|
|
|
- /* UA_EventFieldList_deleteMembers(&del->data.event.fields); */
|
|
|
-
|
|
|
- /* /\* cause an overflowEvent *\/ */
|
|
|
- /* /\* an overflowEvent does not care about event filters and as such */
|
|
|
- /* * will not be "triggered" correctly. Instead, a notification will */
|
|
|
- /* * be inserted into the queue which includes only the nodeId of the */
|
|
|
- /* * overflowEventType. It is up to the client to check for possible */
|
|
|
- /* * overflows. *\/ */
|
|
|
- /* UA_Notification *overflowNotification = (UA_Notification *) UA_malloc(sizeof(UA_Notification)); */
|
|
|
- /* if(!overflowNotification) */
|
|
|
- /* return UA_STATUSCODE_BADOUTOFMEMORY; */
|
|
|
-
|
|
|
- /* UA_EventFieldList_init(&overflowNotification->data.event.fields); */
|
|
|
- /* overflowNotification->data.event.fields.eventFields = UA_Variant_new(); */
|
|
|
- /* if(!overflowNotification->data.event.fields.eventFields) { */
|
|
|
- /* UA_EventFieldList_deleteMembers(&overflowNotification->data.event.fields); */
|
|
|
- /* UA_free(overflowNotification); */
|
|
|
- /* return UA_STATUSCODE_BADOUTOFMEMORY; */
|
|
|
- /* } */
|
|
|
-
|
|
|
- /* UA_Variant_init(overflowNotification->data.event.fields.eventFields); */
|
|
|
- /* overflowNotification->data.event.fields.eventFieldsSize = 1; */
|
|
|
- /* UA_NodeId overflowId = UA_NODEID_NUMERIC(0, UA_NS0ID_SIMPLEOVERFLOWEVENTTYPE); */
|
|
|
- /* UA_Variant_setScalarCopy(overflowNotification->data.event.fields.eventFields, */
|
|
|
- /* &overflowId, &UA_TYPES[UA_TYPES_NODEID]); */
|
|
|
- /* overflowNotification->mon = mon; */
|
|
|
- /* if(mon->discardOldest) { */
|
|
|
- /* TAILQ_INSERT_HEAD(&mon->queue, overflowNotification, listEntry); */
|
|
|
- /* TAILQ_INSERT_HEAD(&mon->subscription->notificationQueue, overflowNotification, globalEntry); */
|
|
|
- /* } else { */
|
|
|
- /* TAILQ_INSERT_TAIL(&mon->queue, overflowNotification, listEntry); */
|
|
|
- /* TAILQ_INSERT_TAIL(&mon->subscription->notificationQueue, overflowNotification, globalEntry); */
|
|
|
- /* } */
|
|
|
- /* ++mon->queueSize; */
|
|
|
- /* ++sub->notificationQueueSize; */
|
|
|
- /* ++sub->eventNotifications; */
|
|
|
- /* } */
|
|
|
+ if(mon->monitoredItemType == UA_MONITOREDITEMTYPE_EVENTNOTIFY) {
|
|
|
+ /* check if an overflowEvent is being deleted
|
|
|
+ * TODO: make sure overflowEvents are never deleted */
|
|
|
+ UA_NodeId overflowBaseId = UA_NODEID_NUMERIC(0, UA_NS0ID_EVENTQUEUEOVERFLOWEVENTTYPE);
|
|
|
+ UA_NodeId overflowId = UA_NODEID_NUMERIC(0, UA_NS0ID_SIMPLEOVERFLOWEVENTTYPE);
|
|
|
+
|
|
|
+ /* Check if an OverflowEvent is being deleted */
|
|
|
+ if (del->data.event.fields.eventFieldsSize == 1
|
|
|
+ && del->data.event.fields.eventFields[0].type == &UA_TYPES[UA_TYPES_NODEID]
|
|
|
+ && isNodeInTree(&server->config.nodestore, (UA_NodeId*)del->data.event.fields.eventFields[0].data,
|
|
|
+ &overflowBaseId, &subtypeId, 1)) {
|
|
|
+ /* Don't do anything, since adding and removing an overflow will not change anything */
|
|
|
+ return UA_STATUSCODE_GOOD;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* cause an overflowEvent */
|
|
|
+ /* an overflowEvent does not care about event filters and as such
|
|
|
+ * will not be "triggered" correctly. Instead, a notification will
|
|
|
+ * be inserted into the queue which includes only the nodeId of the
|
|
|
+ * overflowEventType. It is up to the client to check for possible
|
|
|
+ * overflows. */
|
|
|
+ UA_Notification *overflowNotification = (UA_Notification *) UA_malloc(sizeof(UA_Notification));
|
|
|
+ if(!overflowNotification)
|
|
|
+ return UA_STATUSCODE_BADOUTOFMEMORY;
|
|
|
+
|
|
|
+ UA_EventFieldList_init(&overflowNotification->data.event.fields);
|
|
|
+ overflowNotification->data.event.fields.eventFields = UA_Variant_new();
|
|
|
+ if(!overflowNotification->data.event.fields.eventFields) {
|
|
|
+ UA_EventFieldList_deleteMembers(&overflowNotification->data.event.fields);
|
|
|
+ UA_free(overflowNotification);
|
|
|
+ return UA_STATUSCODE_BADOUTOFMEMORY;
|
|
|
+ }
|
|
|
+
|
|
|
+ overflowNotification->data.event.fields.eventFieldsSize = 1;
|
|
|
+ UA_StatusCode retval = UA_Variant_setScalarCopy(overflowNotification->data.event.fields.eventFields,
|
|
|
+ &overflowId, &UA_TYPES[UA_TYPES_NODEID]);
|
|
|
+ if (retval != UA_STATUSCODE_GOOD) {
|
|
|
+ UA_EventFieldList_deleteMembers(&overflowNotification->data.event.fields);
|
|
|
+ UA_free(overflowNotification);
|
|
|
+ return retval;
|
|
|
+ }
|
|
|
+
|
|
|
+ overflowNotification->mon = mon;
|
|
|
+ if(mon->discardOldest) {
|
|
|
+ TAILQ_INSERT_HEAD(&mon->queue, overflowNotification, listEntry);
|
|
|
+ TAILQ_INSERT_HEAD(&mon->subscription->notificationQueue, overflowNotification, globalEntry);
|
|
|
+ } else {
|
|
|
+ TAILQ_INSERT_TAIL(&mon->queue, overflowNotification, listEntry);
|
|
|
+ TAILQ_INSERT_TAIL(&mon->subscription->notificationQueue, overflowNotification, globalEntry);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /* The amount of notifications in the subscription don't change. The specification
|
|
|
+ * only states that the queue size in each MonitoredItem isn't affected by OverflowEvents.
|
|
|
+ * Since they are reduced in Notification_delete the queues are increased here, so they
|
|
|
+ * will remain the same in the end.
|
|
|
+ */
|
|
|
+ ++sub->notificationQueueSize;
|
|
|
+ ++sub->eventNotifications;
|
|
|
+ }
|
|
|
#endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */
|
|
|
|
|
|
/* Delete the notification. This also removes the notification from the
|