Browse Source

use UA_Server_editNode to reduce code duplication

Julius Pfrommer 9 years ago
parent
commit
23362555a1

+ 4 - 2
include/ua_server.h

@@ -354,10 +354,12 @@ UA_Server_setNodeAttribute_value_destructive(UA_Server *server, const UA_NodeId
 
 /* Succeeds only if the node contains a variant value */
 UA_StatusCode UA_EXPORT
-UA_Server_setAttribute_value_callback(UA_Server *server, UA_NodeId nodeId, UA_ValueCallback callback);
+UA_Server_setAttribute_value_callback(UA_Server *server, const UA_NodeId nodeId,
+                                      const UA_ValueCallback callback);
 
 UA_StatusCode UA_EXPORT
-UA_Server_setNodeAttribute_value_dataSource(UA_Server *server, UA_NodeId nodeId, UA_DataSource dataSource);
+UA_Server_setNodeAttribute_value_dataSource(UA_Server *server, const UA_NodeId nodeId,
+                                            const UA_DataSource dataSource);
 
 /* Don't use this function. There are typed versions with no additional overhead. */
 UA_StatusCode UA_EXPORT

+ 46 - 112
src/server/ua_server.c

@@ -1223,131 +1223,65 @@ UA_Server_setNodeAttribute_value_destructive(UA_Server *server, const UA_NodeId
 }
 
 #ifdef ENABLE_METHODCALLS
-UA_StatusCode
-UA_Server_setNodeAttribute_method(UA_Server *server, UA_NodeId methodNodeId,
-                                  UA_MethodCallback method, void *handle) {
-    UA_StatusCode retval;
- retrySetMethod:
-    retval = UA_STATUSCODE_GOOD;
-  
-    const UA_Node *attachToMethod =  UA_NodeStore_get(server->nodestore, &methodNodeId);
-    if(!attachToMethod)
-        return UA_STATUSCODE_BADNODEIDINVALID;
-  
-    if(attachToMethod->nodeClass != UA_NODECLASS_METHOD) {
-        UA_NodeStore_release(attachToMethod);
-        return UA_STATUSCODE_BADNODEIDINVALID;
-    }
-  
-    UA_MethodNode *replacementMethod = UA_MethodNode_new();
-    if(!replacementMethod) {
-        UA_NodeStore_release(attachToMethod);
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    }
+struct methodAndHandle {
+    UA_MethodCallback method;
+    void *handle;
+};
 
-    retval = UA_MethodNode_copy((const UA_MethodNode *) attachToMethod, replacementMethod);
-    if(retval != UA_STATUSCODE_GOOD) {
-        UA_MethodNode_delete(replacementMethod);
-        UA_NodeStore_release(attachToMethod);
-        return retval;
-    }
-  
-    replacementMethod->attachedMethod = method;
-    replacementMethod->methodHandle   = handle;
-    retval = UA_NodeStore_replace(server->nodestore, attachToMethod, (UA_Node *) replacementMethod, UA_NULL);
-    UA_NodeStore_release(attachToMethod);
+static UA_StatusCode replaceMethod(UA_Server *server, UA_Session *session, UA_MethodNode *node,
+                                   const struct methodAndHandle *mah) {
 
-    /* The node was replaced before we could... */
-    if(retval != UA_STATUSCODE_GOOD)
-        goto retrySetMethod;
-    return retval;
+    if(node->nodeClass != UA_NODECLASS_METHOD)
+        return UA_STATUSCODE_BADNODECLASSINVALID;
+    node->attachedMethod = mah->method;
+    node->methodHandle   = mah->handle;
+    return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Server_setNodeAttribute_method(UA_Server *server, const UA_NodeId methodNodeId,
+                                  UA_MethodCallback method, void *handle) {
+    struct methodAndHandle mah;
+    mah.method = method;
+    mah.handle = handle;
+    return UA_Server_editNode(server, &adminSession, &methodNodeId,
+                              (UA_EditNodeCallback)replaceMethod, &mah);
 }
 #endif
 
+static UA_StatusCode setValueCallback(UA_Server *server, UA_Session *session, UA_VariableNode *node,
+                                      UA_ValueCallback *callback) {
+    if(node->nodeClass != UA_NODECLASS_VARIABLE &&
+       node->nodeClass != UA_NODECLASS_VARIABLETYPE)
+        return UA_STATUSCODE_BADNODECLASSINVALID;
+    node->value.variant.callback = *callback;
+    return UA_STATUSCODE_GOOD;
+}
+
 UA_StatusCode UA_EXPORT
-UA_Server_setAttribute_value_callback(UA_Server *server, UA_NodeId nodeId,
-                                      UA_ValueCallback callback) {
-    const UA_Node *orig;
- retrySetValueCallback:
-    orig = UA_NodeStore_get(server->nodestore, &nodeId);
-    if(!orig)
-        return UA_STATUSCODE_BADNODEIDUNKNOWN;
+UA_Server_setAttribute_value_callback(UA_Server *server, const UA_NodeId nodeId,
+                                      const UA_ValueCallback callback) {
+    return UA_Server_editNode(server, &adminSession, &nodeId,
+                              (UA_EditNodeCallback)setValueCallback, &callback);
+}
 
-    if(orig->nodeClass != UA_NODECLASS_VARIABLE &&
-       orig->nodeClass != UA_NODECLASS_VARIABLETYPE) {
-        UA_NodeStore_release(orig);
+static UA_StatusCode
+setDataSource(UA_Server *server, UA_Session *session, UA_VariableNode* node, UA_DataSource *dataSource) {
+    if(node->nodeClass != UA_NODECLASS_VARIABLE &&
+       node->nodeClass != UA_NODECLASS_VARIABLETYPE)
         return UA_STATUSCODE_BADNODECLASSINVALID;
-    }
-    
-#ifndef UA_MULTITHREADING
-    /* We cheat if multithreading is not enabled and treat the node as mutable. */
-    UA_VariableNode *editable = (UA_VariableNode*)(uintptr_t)orig;
-#else
-    UA_VariableNode *editable = (UA_VariableNode*)UA_Node_copyAnyNodeClass(orig);
-    if(!editable) {
-        UA_NodeStore_release(orig);
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    }
-#endif
-
-    editable->value.variant.callback = callback;
-  
-#ifdef UA_MULTITHREADING
-    UA_StatusCode retval;
-    retval = UA_NodeStore_replace(server->nodestore, orig, (UA_Node*)editable, UA_NULL);
-    if(retval != UA_STATUSCODE_GOOD) {
-        /* The node was replaced in the background */
-        UA_NodeStore_release(orig);
-        goto retrySetValueCallback;
-    }
-#endif
-    UA_NodeStore_release(orig);
+    if(node->valueSource == UA_VALUESOURCE_VARIANT)
+        UA_Variant_deleteMembers(&node->value.variant.value);
+    node->value.dataSource = *dataSource;
+    node->valueSource = UA_VALUESOURCE_DATASOURCE;
     return UA_STATUSCODE_GOOD;
-    
 }
 
 UA_StatusCode
 UA_Server_setNodeAttribute_value_dataSource(UA_Server *server, const UA_NodeId nodeId,
-                                            UA_DataSource dataSource) {
-    const UA_Node *orig;
- retrySetDataSource:
-    orig = UA_NodeStore_get(server->nodestore, &nodeId);
-    if(!orig)
-        return UA_STATUSCODE_BADNODEIDUNKNOWN;
-
-    if(orig->nodeClass != UA_NODECLASS_VARIABLE &&
-       orig->nodeClass != UA_NODECLASS_VARIABLETYPE) {
-        UA_NodeStore_release(orig);
-        return UA_STATUSCODE_BADNODECLASSINVALID;
-    }
-    
-#ifndef UA_MULTITHREADING
-    /* We cheat if multithreading is not enabled and treat the node as mutable. */
-    UA_VariableNode *editable = (UA_VariableNode*)(uintptr_t)orig;
-#else
-    UA_VariableNode *editable = (UA_VariableNode*)UA_Node_copyAnyNodeClass(orig);
-    if(!editable) {
-        UA_NodeStore_release(orig);
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    }
-#endif
-
-    if(editable->valueSource == UA_VALUESOURCE_VARIANT)
-        UA_Variant_deleteMembers(&editable->value.variant.value);
-    editable->value.dataSource = dataSource;
-    editable->valueSource = UA_VALUESOURCE_DATASOURCE;
-  
-#ifdef UA_MULTITHREADING
-    UA_StatusCode retval;
-    retval = UA_NodeStore_replace(server->nodestore, orig, (UA_Node*)editable, UA_NULL);
-    if(retval != UA_STATUSCODE_GOOD) {
-        /* The node was replaced in the background */
-        UA_NodeStore_release(orig);
-        goto retrySetDataSource;
-    }
-#endif
-    UA_NodeStore_release(orig);
-    return UA_STATUSCODE_GOOD;
+                                            const UA_DataSource dataSource) {
+    return UA_Server_editNode(server, &adminSession, &nodeId,
+                              (UA_EditNodeCallback)setDataSource, &dataSource);
 }
 
 UA_StatusCode

+ 2 - 2
src/server/ua_server_internal.h

@@ -74,12 +74,12 @@ struct UA_Server {
 #endif
 };
 
-typedef UA_StatusCode (*UA_EditNodeCallback)(UA_Server *server, UA_Session*, UA_Node*, void*);
+typedef UA_StatusCode (*UA_EditNodeCallback)(UA_Server *server, UA_Session*, UA_Node*, const void*);
 
 /* Calls callback on the node. In the multithreaded case, the node is copied before and replaced in
    the nodestore. */
 UA_StatusCode UA_Server_editNode(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
-                                 UA_EditNodeCallback callback, void *data);
+                                 UA_EditNodeCallback callback, const void *data);
 
 void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection, UA_ByteString *msg);
 

+ 1 - 1
src/server/ua_services_attribute.c

@@ -406,7 +406,7 @@ void Service_Read(UA_Server *server, UA_Session *session, const UA_ReadRequest *
 /*******************/
 
 UA_StatusCode UA_Server_editNode(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
-                                 UA_EditNodeCallback callback, void *data) {
+                                 UA_EditNodeCallback callback, const void *data) {
     UA_StatusCode retval;
     do {
         retval = UA_STATUSCODE_GOOD;

+ 2 - 2
src/server/ua_services_nodemanagement.c

@@ -573,7 +573,7 @@ UA_StatusCode Service_AddReferences_single(UA_Server *server, UA_Session *sessio
     /* cast away the const to loop the call through UA_Server_editNode */
     UA_StatusCode retval = UA_Server_editNode(server, session, &item->sourceNodeId,
                                               (UA_EditNodeCallback)addOneWayReference,
-                                              (void*)(uintptr_t)item);
+                                              item);
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
 
@@ -716,7 +716,7 @@ deleteOneWayReference(UA_Server *server, UA_Session *session, UA_Node *node, con
 UA_StatusCode
 Service_DeleteReferences_single(UA_Server *server, UA_Session *session, const UA_DeleteReferencesItem *item) {
     UA_StatusCode retval = UA_Server_editNode(server, session, &item->sourceNodeId,
-                                       (UA_EditNodeCallback)deleteOneWayReference, (void*)(uintptr_t)item);
+                                       (UA_EditNodeCallback)deleteOneWayReference, item);
     if(!item->deleteBidirectional || item->targetNodeId.serverIndex != 0)
         return retval;
     UA_DeleteReferencesItem secondItem;