Browse Source

simplify browsing; don't get relevant reference types beforehand

Julius Pfrommer 7 years ago
parent
commit
a7b28f5b41
1 changed files with 57 additions and 74 deletions
  1. 57 74
      src/server/ua_services_view.c

+ 57 - 74
src/server/ua_services_view.c

@@ -95,11 +95,8 @@ static void removeCp(struct ContinuationPointEntry *cp, UA_Session* session) {
 
 /* Returns whether the node / continuationpoint is done */
 static UA_Boolean
-browseRelevantReferences(UA_Server *server, UA_BrowseResult *result, const UA_NodeId *relevant_refs,
-                         size_t relevant_refs_size, const UA_BrowseDescription *descr,
-                         struct ContinuationPointEntry *cp) {
-    UA_assert(cp != NULL);
-
+browseReferences(UA_Server *server, const UA_BrowseDescription *descr,
+                 UA_BrowseResult *result, struct ContinuationPointEntry *cp) {
     /* Get the node */
     const UA_Node *node = UA_NodeStore_get(server->nodestore, &descr->nodeId);
     if(!node) {
@@ -117,8 +114,6 @@ browseRelevantReferences(UA_Server *server, UA_BrowseResult *result, const UA_No
     size_t maxrefs = cp->maxReferences;
     if(maxrefs == 0)
         maxrefs = UA_INT32_MAX;
-    else if(maxrefs > node->referencesSize)
-        maxrefs = node->referencesSize;
 
     /* Allocate the results array */
     size_t refs_size = 2; /* True size of the array */
@@ -137,6 +132,7 @@ browseRelevantReferences(UA_Server *server, UA_BrowseResult *result, const UA_No
     }
 
     /* Loop over the node's references */
+    const UA_NodeId hasSubType = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
     for(; referenceKindIndex < node->referencesSize; ++referenceKindIndex) {
         UA_NodeReferenceKind *rk = &node->references[referenceKindIndex];
 
@@ -147,16 +143,15 @@ browseRelevantReferences(UA_Server *server, UA_BrowseResult *result, const UA_No
             continue;
 
         /* Is the reference part of the hierarchy of references we look for? */
-        if(relevant_refs) {
-            UA_Boolean is_relevant = false;
-            for(size_t i = 0; i < relevant_refs_size; ++i) {
-                if(UA_NodeId_equal(&rk->referenceTypeId, &relevant_refs[i])) {
-                    is_relevant = true;
-                    break;
-                }
+        if(!UA_NodeId_isNull(&descr->referenceTypeId)) {
+            if(!descr->includeSubtypes) {
+                if(!UA_NodeId_equal(&descr->referenceTypeId, &rk->referenceTypeId))
+                    continue;
+            } else {
+                if(!isNodeInTree(server->nodestore, &rk->referenceTypeId,
+                                 &descr->referenceTypeId, &hasSubType, 1))
+                    continue;
             }
-            if(!is_relevant)
-                continue;
         }
 
         /* Loop over the targets */
@@ -191,10 +186,6 @@ browseRelevantReferences(UA_Server *server, UA_BrowseResult *result, const UA_No
             /* Copy the node description */
             result->statusCode = fillReferenceDescription(server, target, rk, descr->resultMask,
                                                           &result->references[result->referencesSize]);
-/* fillReferenceDescription(UA_Server *server, const UA_Node *curr, */
-/*                          const UA_NodeReferenceKind *ref, */
-/*                          const UA_ExpandedNodeId *target, UA_UInt32 mask, */
-/*                          UA_ReferenceDescription *descr) { */
             if(result->statusCode != UA_STATUSCODE_GOOD)
                 goto error_recovery;
 
@@ -260,34 +251,8 @@ Service_Browse_single(UA_Server *server, UA_Session *session,
         return;
     }
 
-    /* Get the references that match the browsedescription. reftypes == NULL
-     * indicates that all references shall be returned. */
-    size_t reftypesSize = 0;
-    UA_NodeId *reftypes = NULL;
-    UA_Boolean all_refs = UA_NodeId_isNull(&descr->referenceTypeId);
-    if(!all_refs) {
-        const UA_Node *rootRef = UA_NodeStore_get(server->nodestore, &descr->referenceTypeId);
-        if(!rootRef || rootRef->nodeClass != UA_NODECLASS_REFERENCETYPE) {
-            result->statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
-            return;
-        }
-        if(descr->includeSubtypes) {
-            result->statusCode = getTypeHierarchy(server->nodestore, rootRef, false,
-                                                  &reftypes, &reftypesSize);
-            if(result->statusCode != UA_STATUSCODE_GOOD)
-                return;
-        } else {
-            reftypes = (UA_NodeId*)(uintptr_t)&descr->referenceTypeId;
-            reftypesSize = 1;
-        }
-    }
-
-    /* Browse with the relevant references */
-    UA_Boolean done = browseRelevantReferences(server, result, reftypes, reftypesSize, descr, internal_cp);
-
-    /* Clean up the array of relevant references */
-    if(!all_refs && descr->includeSubtypes)
-        UA_Array_delete(reftypes, reftypesSize, &UA_TYPES[UA_TYPES_NODEID]);
+    /* Browse the references */
+    UA_Boolean done = browseReferences(server, descr, result, internal_cp);
 
     /* Exit early if an error occured */
     if(result->statusCode != UA_STATUSCODE_GOOD)
@@ -329,9 +294,12 @@ Service_Browse_single(UA_Server *server, UA_Session *session,
     }
 }
 
-void Service_Browse(UA_Server *server, UA_Session *session, const UA_BrowseRequest *request,
+void Service_Browse(UA_Server *server, UA_Session *session,
+                    const UA_BrowseRequest *request,
                     UA_BrowseResponse *response) {
-    UA_LOG_DEBUG_SESSION(server->config.logger, session, "Processing BrowseRequest");
+    UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                         "Processing BrowseRequest");
+
     if(!UA_NodeId_isNull(&request->view.viewId)) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADVIEWIDUNKNOWN;
         return;
@@ -343,7 +311,8 @@ void Service_Browse(UA_Server *server, UA_Session *session, const UA_BrowseReque
     }
 
     size_t size = request->nodesToBrowseSize;
-    response->results = (UA_BrowseResult *)UA_Array_new(size, &UA_TYPES[UA_TYPES_BROWSERESULT]);
+    response->results =
+        (UA_BrowseResult*)UA_Array_new(size, &UA_TYPES[UA_TYPES_BROWSERESULT]);
     if(!response->results) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
         return;
@@ -387,41 +356,52 @@ void Service_Browse(UA_Server *server, UA_Session *session, const UA_BrowseReque
 }
 
 UA_BrowseResult
-UA_Server_browse(UA_Server *server, UA_UInt32 maxrefs, const UA_BrowseDescription *descr) {
+UA_Server_browse(UA_Server *server, UA_UInt32 maxrefs,
+                 const UA_BrowseDescription *descr) {
     UA_BrowseResult result;
     UA_BrowseResult_init(&result);
     UA_RCU_LOCK();
-    Service_Browse_single(server, &adminSession, NULL, descr, maxrefs, &result);
+    Service_Browse_single(server, &adminSession, NULL,
+                          descr, maxrefs, &result);
     UA_RCU_UNLOCK();
     return result;
 }
 
 static void
-UA_Server_browseNext_single(UA_Server *server, UA_Session *session, UA_Boolean releaseContinuationPoint,
-                            const UA_ByteString *continuationPoint, UA_BrowseResult *result) {
-    result->statusCode = UA_STATUSCODE_BADCONTINUATIONPOINTINVALID;
-    struct ContinuationPointEntry *cp, *temp;
-    LIST_FOREACH_SAFE(cp, &session->continuationPoints, pointers, temp) {
-        if(UA_ByteString_equal(&cp->identifier, continuationPoint)) {
-            result->statusCode = UA_STATUSCODE_GOOD;
-            if(!releaseContinuationPoint)
-                Service_Browse_single(server, session, cp, NULL, 0, result);
-            else
-                removeCp(cp, session);
+UA_Server_browseNext_single(UA_Server *server, UA_Session *session,
+                            UA_Boolean releaseContinuationPoint,
+                            const UA_ByteString *continuationPoint,
+                            UA_BrowseResult *result) {
+    /* Find the continuation point */
+    struct ContinuationPointEntry *cp;
+    LIST_FOREACH(cp, &session->continuationPoints, pointers) {
+        if(UA_ByteString_equal(&cp->identifier, continuationPoint))
             break;
-        }
     }
+    if(!cp) {
+        result->statusCode = UA_STATUSCODE_BADCONTINUATIONPOINTINVALID;
+        return;
+    }
+
+    /* Do the work */
+    if(!releaseContinuationPoint)
+        Service_Browse_single(server, session, cp, NULL, 0, result);
+    else
+        removeCp(cp, session);
 }
 
-void Service_BrowseNext(UA_Server *server, UA_Session *session, const UA_BrowseNextRequest *request,
+void Service_BrowseNext(UA_Server *server, UA_Session *session,
+                        const UA_BrowseNextRequest *request,
                         UA_BrowseNextResponse *response) {
-    UA_LOG_DEBUG_SESSION(server->config.logger, session, "Processing BrowseNextRequest");
+    UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                         "Processing BrowseNextRequest");
     if(request->continuationPointsSize <= 0) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
         return;
     }
     size_t size = request->continuationPointsSize;
-    response->results = (UA_BrowseResult *)UA_Array_new(size, &UA_TYPES[UA_TYPES_BROWSERESULT]);
+    response->results =
+        (UA_BrowseResult*)UA_Array_new(size, &UA_TYPES[UA_TYPES_BROWSERESULT]);
     if(!response->results) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
         return;
@@ -429,8 +409,10 @@ void Service_BrowseNext(UA_Server *server, UA_Session *session, const UA_BrowseN
 
     response->resultsSize = size;
     for(size_t i = 0; i < size; ++i)
-        UA_Server_browseNext_single(server, session, request->releaseContinuationPoints,
-                                    &request->continuationPoints[i], &response->results[i]);
+        UA_Server_browseNext_single(server, session,
+                                    request->releaseContinuationPoints,
+                                    &request->continuationPoints[i],
+                                    &response->results[i]);
 }
 
 UA_BrowseResult
@@ -480,7 +462,8 @@ walkBrowsePathElementNodeReference(UA_BrowsePathResult *result, size_t *targetsS
          * targets with the right path "depth" */
         if(targetId->serverIndex != 0) {
             UA_BrowsePathTarget *tempTargets =
-                (UA_BrowsePathTarget *)UA_realloc(result->targets, sizeof(UA_BrowsePathTarget) * (*targetsSize) * 2);
+                (UA_BrowsePathTarget*)UA_realloc(result->targets,
+                             sizeof(UA_BrowsePathTarget) * (*targetsSize) * 2);
             if(!tempTargets) {
                 result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
                 return;
@@ -488,14 +471,15 @@ walkBrowsePathElementNodeReference(UA_BrowsePathResult *result, size_t *targetsS
             result->targets = tempTargets;
             (*targetsSize) *= 2;
             result->statusCode = UA_ExpandedNodeId_copy(targetId,
-                                                        &result->targets[result->targetsSize].targetId);
+                       &result->targets[result->targetsSize].targetId);
             result->targets[result->targetsSize].remainingPathIndex = elemDepth;
             continue;
         }
 
         /* Can we store the node in the array of candidates for deep-search? */
         if(*nextSize <= *nextCount) {
-            UA_NodeId *tempNext = (UA_NodeId *)UA_realloc(*next, sizeof(UA_NodeId) * (*nextSize) * 2);
+            UA_NodeId *tempNext =
+                (UA_NodeId*)UA_realloc(*next, sizeof(UA_NodeId) * (*nextSize) * 2);
             if(!tempNext) {
                 result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
                 return;
@@ -555,7 +539,6 @@ walkBrowsePathElement(UA_Server *server, UA_Session *session,
                           !UA_String_equal(&targetName->name, &node->browseName.name)))
             continue;
 
-        /* Walk over the references in the node */
         /* Loop over the nodes references */
         for(size_t r = 0; r < node->referencesSize &&
                 result->statusCode == UA_STATUSCODE_GOOD; ++r) {