Browse Source

Making the resource limitations of subscriptions global

By making the resource limitations for subscriptions and monitored
items global in the server, the sessions can share the resource
limitations instead of splitting the resources evenly over the
supported sessions.
This change allow servers to support profile requirements with less
resources. E.g. the Embedded UA server profile sets minimum
requirements on number of subscriptions for a session and number of
monitored items for a subscription. But the profile does not require
all sessions or all subscriptions to meet these requirements
concurrently.
Jonas Green 6 years ago
parent
commit
8c2e984ae4

+ 2 - 2
include/open62541/server_config.h

@@ -150,7 +150,7 @@ struct UA_ServerConfig {
     UA_UInt32 maxReferencesPerNode;
 
     /* Limits for Subscriptions */
-    UA_UInt32 maxSubscriptionsPerSession;
+    UA_UInt32 maxSubscriptions;
     UA_DurationRange publishingIntervalLimits; /* in ms (must not be less than 5) */
     UA_UInt32Range lifeTimeCountLimits;
     UA_UInt32Range keepAliveCountLimits;
@@ -162,7 +162,7 @@ struct UA_ServerConfig {
 #endif
 
     /* Limits for MonitoredItems */
-    UA_UInt32 maxMonitoredItemsPerSubscription;
+    UA_UInt32 maxMonitoredItems;
     UA_DurationRange samplingIntervalLimits; /* in ms (must not be less than 5) */
     UA_UInt32Range queueSizeLimits; /* Negotiated with the client */
 

+ 5 - 1
src/server/ua_server_internal.h

@@ -79,8 +79,12 @@ struct UA_Server {
     UA_DiscoveryManager discoveryManager;
 #endif
 
-    /* Local MonitoredItems */
+    /* DataChange Subscriptions */
 #ifdef UA_ENABLE_SUBSCRIPTIONS
+    /* Num active subscriptions */
+    UA_UInt32 numSubscriptions;
+    /* Num active monitored items */
+    UA_UInt32 numMonitoredItems;
     /* To be cast to UA_LocalMonitoredItem to get the callback and context */
     LIST_HEAD(LocalMonitoredItems, UA_MonitoredItem) localMonitoredItems;
     UA_UInt32 lastLocalMonitoredItemId;

+ 6 - 6
src/server/ua_services_subscription.c

@@ -69,8 +69,8 @@ Service_CreateSubscription(UA_Server *server, UA_Session *session,
                            const UA_CreateSubscriptionRequest *request,
                            UA_CreateSubscriptionResponse *response) {
     /* Check limits for the number of subscriptions */
-    if((server->config.maxSubscriptionsPerSession != 0) &&
-       (session->numSubscriptions >= server->config.maxSubscriptionsPerSession)) {
+    if((server->config.maxSubscriptions != 0) &&
+       (server->numSubscriptions >= server->config.maxSubscriptions)) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYSUBSCRIPTIONS;
         return;
     }
@@ -84,7 +84,7 @@ Service_CreateSubscription(UA_Server *server, UA_Session *session,
         return;
     }
 
-    UA_Session_addSubscription(session, newSubscription); /* Also assigns the subscription id */
+    UA_Session_addSubscription(server, session, newSubscription); /* Also assigns the subscription id */
 
     /* Set the subscription parameters */
     newSubscription->publishingEnabled = request->publishingEnabled;
@@ -280,8 +280,8 @@ Operation_CreateMonitoredItem(UA_Server *server, UA_Session *session, struct cre
                               const UA_MonitoredItemCreateRequest *request,
                               UA_MonitoredItemCreateResult *result) {
     /* Check available capacity */
-    if(server->config.maxMonitoredItemsPerSubscription != 0 && cmc->sub &&
-       cmc->sub->monitoredItemsSize >= server->config.maxMonitoredItemsPerSubscription) {
+    if(server->config.maxMonitoredItems != 0 && cmc->sub &&
+       server->numMonitoredItems >= server->config.maxMonitoredItems) {
         result->statusCode = UA_STATUSCODE_BADTOOMANYMONITOREDITEMS;
         return;
     }
@@ -354,7 +354,7 @@ Operation_CreateMonitoredItem(UA_Server *server, UA_Session *session, struct cre
     /* Add to the subscriptions or the local MonitoredItems */
     if(cmc->sub) {
         newMon->monitoredItemId = ++cmc->sub->lastMonitoredItemId;
-        UA_Subscription_addMonitoredItem(cmc->sub, newMon);
+        UA_Subscription_addMonitoredItem(server, cmc->sub, newMon);
 #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
         if(newMon->monitoredItemType == UA_MONITOREDITEMTYPE_EVENTNOTIFY) {
             /* Insert the monitored item into the node's queue */

+ 4 - 1
src/server/ua_session.c

@@ -76,11 +76,12 @@ void UA_Session_updateLifetime(UA_Session *session) {
 
 #ifdef UA_ENABLE_SUBSCRIPTIONS
 
-void UA_Session_addSubscription(UA_Session *session, UA_Subscription *newSubscription) {
+void UA_Session_addSubscription(UA_Server *server, UA_Session *session, UA_Subscription *newSubscription) {
     newSubscription->subscriptionId = ++session->lastSubscriptionId;
 
     LIST_INSERT_HEAD(&session->serverSubscriptions, newSubscription, listEntry);
     session->numSubscriptions++;
+    server->numSubscriptions++;
 }
 
 UA_StatusCode
@@ -101,7 +102,9 @@ UA_Session_deleteSubscription(UA_Server *server, UA_Session *session,
     /* Remove from the session */
     LIST_REMOVE(sub, listEntry);
     UA_assert(session->numSubscriptions > 0);
+    UA_assert(server->numSubscriptions > 0);
     session->numSubscriptions--;
+    server->numSubscriptions--;
     return UA_STATUSCODE_GOOD;
 }
 

+ 2 - 1
src/server/ua_session.h

@@ -83,7 +83,8 @@ void UA_Session_updateLifetime(UA_Session *session);
 #ifdef UA_ENABLE_SUBSCRIPTIONS
 
 void
-UA_Session_addSubscription(UA_Session *session,
+UA_Session_addSubscription(UA_Server *server,
+                           UA_Session *session,
                            UA_Subscription *newSubscription);
 
 UA_Subscription *

+ 7 - 1
src/server/ua_subscription.c

@@ -55,6 +55,8 @@ UA_Subscription_deleteMembers(UA_Server *server, UA_Subscription *sub) {
                             mon->monitoredItemId);
         UA_MonitoredItem_delete(server, mon);
     }
+    UA_assert(server->numMonitoredItems >= sub->monitoredItemsSize);
+    server->numMonitoredItems -= sub->monitoredItemsSize;
     sub->monitoredItemsSize = 0;
 
     /* Delete Retransmission Queue */
@@ -102,7 +104,10 @@ UA_Subscription_deleteMonitoredItem(UA_Server *server, UA_Subscription *sub,
 
     /* Remove the MonitoredItem */
     LIST_REMOVE(mon, listEntry);
+    UA_assert(sub->monitoredItemsSize > 0);
+    UA_assert(server->numMonitoredItems > 0);
     sub->monitoredItemsSize--;
+    server->numMonitoredItems--;
 
     /* Remove content and delayed free */
     UA_MonitoredItem_delete(server, mon);
@@ -111,8 +116,9 @@ UA_Subscription_deleteMonitoredItem(UA_Server *server, UA_Subscription *sub,
 }
 
 void
-UA_Subscription_addMonitoredItem(UA_Subscription *sub, UA_MonitoredItem *newMon) {
+UA_Subscription_addMonitoredItem(UA_Server *server, UA_Subscription *sub, UA_MonitoredItem *newMon) {
     sub->monitoredItemsSize++;
+    server->numMonitoredItems++;
     LIST_INSERT_HEAD(&sub->monitoredItems, newMon, listEntry);
 }
 

+ 2 - 2
src/server/ua_subscription.h

@@ -1,6 +1,6 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. 
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  *    Copyright 2015-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
  *    Copyright 2015 (c) Chris Iatrou
@@ -220,7 +220,7 @@ UA_Subscription * UA_Subscription_new(UA_Session *session, UA_UInt32 subscriptio
 void UA_Subscription_deleteMembers(UA_Server *server, UA_Subscription *sub);
 UA_StatusCode Subscription_registerPublishCallback(UA_Server *server, UA_Subscription *sub);
 void Subscription_unregisterPublishCallback(UA_Server *server, UA_Subscription *sub);
-void UA_Subscription_addMonitoredItem(UA_Subscription *sub, UA_MonitoredItem *newMon);
+void UA_Subscription_addMonitoredItem(UA_Server *server, UA_Subscription *sub, UA_MonitoredItem *newMon);
 UA_MonitoredItem * UA_Subscription_getMonitoredItem(UA_Subscription *sub, UA_UInt32 monitoredItemId);
 
 UA_StatusCode