Explorar o código

first version of object constructor and destructor

Julius Pfrommer %!s(int64=9) %!d(string=hai) anos
pai
achega
6c4afaabae

+ 9 - 0
include/ua_server.h

@@ -428,6 +428,15 @@ UA_Server_setNodeAttribute_method(UA_Server *server, UA_NodeId methodNodeId,
                                   UA_MethodCallback method, void *handle);
 #endif
 
+typedef struct {
+    void * (*constructor)(const UA_NodeId instance); ///< Returns the instance handle attached to the node
+    void (*destructor)(const UA_NodeId instance, void *instanceHandle);
+} UA_ObjectInstanceManagement;
+
+UA_StatusCode UA_EXPORT
+UA_Server_setObjectInstanceManagement(UA_Server *server, UA_NodeId nodeId,
+                                      UA_ObjectInstanceManagement oim);
+
 /***********************/
 /* Get Node Attributes */
 /***********************/

+ 6 - 2
src/server/ua_nodes.c

@@ -141,6 +141,7 @@ void UA_ObjectNode_init(UA_ObjectNode *p) {
 	UA_Node_init((UA_Node*)p);
     p->nodeClass = UA_NODECLASS_OBJECT;
     p->eventNotifier = 0;
+    p->instanceHandle = UA_NULL;
 }
 
 UA_ObjectNode * UA_ObjectNode_new(void) {
@@ -161,6 +162,7 @@ void UA_ObjectNode_delete(UA_ObjectNode *p) {
 
 UA_StatusCode UA_ObjectNode_copy(const UA_ObjectNode *src, UA_ObjectNode *dst) {
     dst->eventNotifier = src->eventNotifier;
+    dst->instanceHandle = src->instanceHandle;
 	return UA_Node_copy((const UA_Node*)src, (UA_Node*)dst);
 }
 
@@ -169,6 +171,7 @@ void UA_ObjectTypeNode_init(UA_ObjectTypeNode *p) {
 	UA_Node_init((UA_Node*)p);
     p->nodeClass = UA_NODECLASS_OBJECTTYPE;
     p->isAbstract = UA_FALSE;
+    p->instanceManagement = (UA_ObjectInstanceManagement){UA_NULL};
 }
 
 UA_ObjectTypeNode * UA_ObjectTypeNode_new(void) {
@@ -189,6 +192,7 @@ void UA_ObjectTypeNode_delete(UA_ObjectTypeNode *p) {
 
 UA_StatusCode UA_ObjectTypeNode_copy(const UA_ObjectTypeNode *src, UA_ObjectTypeNode *dst) {
     dst->isAbstract = src->isAbstract;
+    dst->instanceManagement = src->instanceManagement;
 	return UA_Node_copy((const UA_Node*)src, (UA_Node*)dst);
 }
 
@@ -229,10 +233,10 @@ UA_StatusCode UA_VariableNode_copy(const UA_VariableNode *src, UA_VariableNode *
 	UA_StatusCode retval = UA_Node_copy((const UA_Node*)src, (UA_Node*)dst);
     dst->valueRank = src->valueRank;
     dst->valueSource = src->valueSource;
-    if(src->valueSource == UA_VALUESOURCE_VARIANT){
+    if(src->valueSource == UA_VALUESOURCE_VARIANT) {
         retval = UA_Variant_copy(&src->value.variant.value, &dst->value.variant.value);
         dst->value.variant.callback = src->value.variant.callback;
-    }else
+    } else
         dst->value.dataSource = src->value.dataSource;
     if(retval) {
         UA_VariableNode_deleteMembers(dst);

+ 2 - 0
src/server/ua_nodes.h

@@ -37,6 +37,7 @@ UA_Node * UA_Node_copyAnyNodeClass(const UA_Node *node);
 typedef struct {
     UA_STANDARD_NODEMEMBERS
     UA_Byte eventNotifier;
+    void *instanceHandle;
 } UA_ObjectNode;
 UA_TYPE_HANDLING_FUNCTIONS(UA_ObjectNode)
 
@@ -47,6 +48,7 @@ UA_TYPE_HANDLING_FUNCTIONS(UA_ObjectNode)
 typedef struct {
     UA_STANDARD_NODEMEMBERS
     UA_Boolean isAbstract;
+    UA_ObjectInstanceManagement instanceManagement;
 } UA_ObjectTypeNode;
 UA_TYPE_HANDLING_FUNCTIONS(UA_ObjectTypeNode)
 

+ 16 - 0
src/server/ua_server.c

@@ -1284,6 +1284,22 @@ UA_Server_setNodeAttribute_value_dataSource(UA_Server *server, const UA_NodeId n
                               (UA_EditNodeCallback)setDataSource, &dataSource);
 }
 
+static UA_StatusCode
+setObjectManagement(UA_Server *server, UA_Session *session, UA_ObjectTypeNode* node,
+                    UA_ObjectInstanceManagement *oim) {
+    if(node->nodeClass != UA_NODECLASS_OBJECTTYPE)
+        return UA_STATUSCODE_BADNODECLASSINVALID;
+    node->instanceManagement = *oim;
+    return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode UA_EXPORT
+UA_Server_setObjectInstanceManagement(UA_Server *server, UA_NodeId nodeId,
+                                      UA_ObjectInstanceManagement oim) {
+    return UA_Server_editNode(server, &adminSession, &nodeId,
+                              (UA_EditNodeCallback)setObjectManagement, &oim);
+}
+
 UA_StatusCode
 UA_Server_getNodeAttribute(UA_Server *server, const UA_NodeId nodeId,
                            const UA_AttributeId attributeId, void *v) {

+ 38 - 3
src/server/ua_services_nodemanagement.c

@@ -140,9 +140,30 @@ Service_AddNodes_single_fromVariableAttributes(UA_Server *server, UA_Session *se
         UA_VariableNode_delete(vnode);
 }
 
+static UA_StatusCode
+setInstanceHandle(UA_Server *server, UA_Session *session, UA_ObjectNode *node, void *instanceHandle) {
+    node->instanceHandle = instanceHandle;
+    return UA_STATUSCODE_GOOD;
+}
+
 static void
 Service_AddNodes_single_fromObjectAttributes(UA_Server *server, UA_Session *session, UA_AddNodesItem *item,
                                              UA_ObjectAttributes *attr, UA_AddNodesResult *result) {
+    /* Get the parent node */
+    const UA_Node *parent = UA_NULL;
+    if(!UA_NodeId_isNull(&item->parentNodeId.nodeId)) {
+        parent = UA_NodeStore_get(server->nodestore, &item->parentNodeId.nodeId);
+        if(!parent) {
+            result->statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID;
+            return;
+        }
+        if(parent->nodeClass == UA_NODECLASS_OBJECTTYPE) {
+            UA_NodeStore_release(parent);
+            result->statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID;
+            return;
+        }
+    }
+    
     UA_ObjectNode *onode = UA_ObjectNode_new();
     if(!onode) {
         result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
@@ -154,13 +175,27 @@ Service_AddNodes_single_fromObjectAttributes(UA_Server *server, UA_Session *sess
 
     UA_Server_addExistingNode(server, session, (UA_Node*)onode, &item->parentNodeId.nodeId,
                               &item->referenceTypeId, result);
-    if(result->statusCode != UA_STATUSCODE_GOOD)
+    if(result->statusCode != UA_STATUSCODE_GOOD) {
         UA_ObjectNode_delete(onode);
+        return;
+    }
+
+    if(!parent)
+        return;
+
+    /* call the constructor */
+    void *instanceHandle =
+        ((const UA_ObjectTypeNode*)parent)->instanceManagement.constructor(result->addedNodeId);
+    UA_Server_editNode(server, session, &result->addedNodeId,
+                (UA_EditNodeCallback)setInstanceHandle, instanceHandle);
+    UA_NodeStore_release(parent);
+    return;
 }
 
 static void
-Service_AddNodes_single_fromReferenceTypeAttributes(UA_Server *server, UA_Session *session, UA_AddNodesItem *item,
-                                                    UA_ReferenceTypeAttributes *attr, UA_AddNodesResult *result) {
+Service_AddNodes_single_fromReferenceTypeAttributes(UA_Server *server, UA_Session *session,
+                                                    UA_AddNodesItem *item, UA_ReferenceTypeAttributes *attr,
+                                                    UA_AddNodesResult *result) {
     UA_ReferenceTypeNode *rtnode = UA_ReferenceTypeNode_new();
     if(!rtnode) {
         result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;