High Performance OPC UA Server SDK
1.5.2.321
|
The SDK implements the UA FileType as defined by "Annex C File Transfer" - "OPC UA Specification - Part 5: Information Model".
The purpose of the FileType is to be able to transfer file contents, that might be exceeding the maximum message size of UA by adding methods which allow to read and write parts of files. In addition it provides functionality for locking files and read file meta data. See specification for more details on the FileType itself.
To understand the SDK architecture of the FileType you must first understand that the FileType that is visible via OPC UA address space is independent from the technical filetype used in the code. So it is possible that you have multiple instances of the same UA FileType, which use different file implementations. So one instance might be connected with a real filesystem file, another instance might be an in-memory file.
To achieve this the SDK defines a ua_filetype_interface, which is a calltable to the actual file implementation, and a ua_file_context, which represents one instance of a real file. This ua_file_context holds file meta data as well as the ua_filetype_interface to use for this instance. The UA node in the address space, which represents a file, is connected to such a ua_file_context. The type ua_file_handle represents and opened file with its meta data like e.g. the file position.
The SDK infrastructure takes care of handling UA file method invocations, locking and cleanup of file resources. E.g. if a session gets deleted or a file is not used for a configurable time (file_timeout), then the file gets closed automatically and the associated file handle gets removed.
The SDK provides two default implementations of a FileType.
SUPPORT_FILE_IO
, also the ua_filesystem_implementation SUPPORT_FILE_IO depends on this option and is unavailable if this option was disabled.The function ua_filetype_create_ex does two things in one step. It creates the instance of the specified file type (UA_NODE_FILETYPE
in this example), and it creates a underlying file context and connects both.
Creating the instance in address space works the same way is ua_instance_new.
Code snippet from the demoprovider:
Creating an in-memory file works essentially the same as the example above, with the following differences:
The following example uses ua_filetype_create instead of ua_filetype_create_ex to demonstrate this. This is just a convenience wrapper function, so that you don't need to create the ua_filetype_ctx yourself. This function is sufficient for most cases, but if you need control over the created NodeIds you must use ua_filetype_create_ex and register the according callbacks.
If you need other kinds of files you can add your own implementation of the file interface. All you need to do is creating an instance of ua_filetype_interface and set the function pointers of your implementation. Then use this calltable in ua_filetype_create like for the examples above.
The args
argument of ua_filetype_create_ex will be forwarded to the create
function of ua_filetype_interface. This way you can pass implementation specific data to your implementation. This private implementation details can be stored in the pimpl
field of the ua_file_context. So this is available in all the function calls.
To understand this it's best to look at the existing two implementations which are shown in the UML diagrams below.