Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ protected override NodeState AddBehaviourToPredefinedNode(
}
else
{
NodeState serverNode = FindNodeInAddressSpace(ObjectIds.Server);
NodeState serverNode = Server.NodeManager.FindNodeInAddressSpaceAsync(ObjectIds.Server).AsTask().GetAwaiter().GetResult();
serverNode?.ReplaceChild(context, activeNode);
}
// remove the reference to server node because it is set as parent
Expand Down Expand Up @@ -1192,8 +1192,8 @@ private NamespaceMetadataState FindNamespaceMetadataState(string namespaceUri)
var nameSpaceNodeId = ExpandedNodeId.ToNodeId(
serverNamespacesReference.TargetId,
Server.NamespaceUris);
if (FindNodeInAddressSpace(
nameSpaceNodeId) is not NamespaceMetadataState namespaceMetadata)
if (Server.NodeManager.FindNodeInAddressSpaceAsync(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we not just make this method async, too? All the way up to "start"? We could lave the sync one and deprecate it. WIth a pointer to how the behavior inside it has changed anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Async will be done with AsyncCustomNodeManager being added soon.

nameSpaceNodeId).AsTask().GetAwaiter().GetResult() is not NamespaceMetadataState namespaceMetadata)
{
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace Opc.Ua.Server
/// <summary>
/// The Server Configuration Node Manager.
/// </summary>
public interface IConfigurationNodeManager : INodeManager2
public interface IConfigurationNodeManager : INodeManager3
{
/// <summary>
/// Gets or creates the <see cref="NamespaceMetadataState"/> node for the specified NamespaceUri.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace Opc.Ua.Server
/// <summary>
/// A node manager the diagnostic information exposed by the server.
/// </summary>
public interface IDiagnosticsNodeManager : INodeManager2, INodeIdFactory
public interface IDiagnosticsNodeManager : INodeManager3, INodeIdFactory
{
/// <summary>
/// True if diagnostics are currently enabled.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,38 @@ public ValueTask WriteAsync(
return default;
}

/// <inheritdoc/>
public ValueTask<ServiceResult> ValidateEventRolePermissionsAsync(IEventMonitoredItem monitoredItem, IFilterTarget filterTarget)
{
if (SyncNodeManager is IAsyncNodeManager asyncNodeManager)
{
return asyncNodeManager.ValidateEventRolePermissionsAsync(monitoredItem, filterTarget);
}

if (SyncNodeManager is INodeManager3 nodeManager2)
{
return new ValueTask<ServiceResult>(nodeManager2.ValidateEventRolePermissions(monitoredItem, filterTarget));
}

return new ValueTask<ServiceResult>(ServiceResult.Good);
}

/// <inheritdoc/>
public ValueTask<ServiceResult> ValidateRolePermissionsAsync(OperationContext operationContext, NodeId nodeId, PermissionType requestedPermission)
{
if (SyncNodeManager is IAsyncNodeManager asyncNodeManager)
{
return asyncNodeManager.ValidateRolePermissionsAsync(operationContext, nodeId, requestedPermission);
}

if (SyncNodeManager is INodeManager3 nodeManager2)
{
return new ValueTask<ServiceResult>(nodeManager2.ValidateRolePermissions(operationContext, nodeId, requestedPermission));
}

return new ValueTask<ServiceResult>(ServiceResult.Good);
}

/// <summary>
/// Frees any unmanaged resources.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ public static class SyncNodeManagerAdapterFactory
/// if the NodeManager does not implement the interface uses the <see cref="SyncNodeManagerAdapter"/>
/// to create an ISyncNodeManager compatible object
/// </summary>
public static INodeManager2 ToSyncNodeManager(this IAsyncNodeManager nodeManager)
public static INodeManager3 ToSyncNodeManager(this IAsyncNodeManager nodeManager)
{
if (nodeManager is INodeManager2 syncNodeManager)
if (nodeManager is INodeManager3 syncNodeManager)
{
return syncNodeManager;
}
Expand All @@ -59,7 +59,7 @@ public static INodeManager2 ToSyncNodeManager(this IAsyncNodeManager nodeManager
/// This allows asynchronous nodeManagers to be treated as synchronous, which can help
/// compatibility with existing code.
/// </remarks>
public class SyncNodeManagerAdapter : INodeManager2
public class SyncNodeManagerAdapter : INodeManager3
{
/// <summary>
/// Initializes a new instance of the <see cref="SyncNodeManagerAdapter"/> class.
Expand Down Expand Up @@ -288,6 +288,18 @@ public NodeMetadata GetPermissionMetadata(
.AsTask().GetAwaiter().GetResult();
}

/// <inheritdoc/>
public ServiceResult ValidateEventRolePermissions(IEventMonitoredItem monitoredItem, IFilterTarget filterTarget)
{
return m_nodeManager.ValidateEventRolePermissionsAsync(monitoredItem, filterTarget).AsTask().GetAwaiter().GetResult();
}

/// <inheritdoc/>
public ServiceResult ValidateRolePermissions(OperationContext operationContext, NodeId nodeId, PermissionType requestedPermission)
{
return m_nodeManager.ValidateRolePermissionsAsync(operationContext, nodeId, requestedPermission).AsTask().GetAwaiter().GetResult();
}

private readonly IAsyncNodeManager m_nodeManager;
}
}
20 changes: 4 additions & 16 deletions Libraries/Opc.Ua.Server/NodeManager/CustomNodeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ namespace Opc.Ua.Server
/// is not part of the SDK because most real implementations of a INodeManager will need to
/// modify the behavior of the base class.
/// </remarks>
public partial class CustomNodeManager2 : INodeManager2, INodeIdFactory, IDisposable
public partial class CustomNodeManager2 : INodeManager3, INodeIdFactory, IDisposable
{
/// <summary>
/// Initializes the node manager.
Expand Down Expand Up @@ -169,7 +169,7 @@ protected CustomNodeManager2(
}
else
{
m_monitoredItemManager = new MonitoredNodeMonitoredItemManager(this);
m_monitoredItemManager = new MonitoredNodeMonitoredItemManager(this, server);
}

PredefinedNodes = [];
Expand Down Expand Up @@ -445,22 +445,10 @@ public bool DeleteNode(ServerSystemContext context, NodeId nodeId)
/// <summary>
/// Searches the node id in all node managers
/// </summary>
[Obsolete("Use IServerInteral.IMasterNodeManager.FindNodeInAddressSpaceAsync instead.")]
public NodeState FindNodeInAddressSpace(NodeId nodeId)
{
if (nodeId.IsNull)
{
return null;
}
// search node id in all node managers
foreach (INodeManager nodeManager in Server.NodeManager.NodeManagers)
{
if (nodeManager.GetManagerHandle(nodeId) is not NodeHandle handle)
{
continue;
}
return handle.Node;
}
return null;
return Server.NodeManager.FindNodeInAddressSpaceAsync(nodeId).AsTask().GetAwaiter().GetResult();
}

/// <summary>
Expand Down
6 changes: 6 additions & 0 deletions Libraries/Opc.Ua.Server/NodeManager/IMasterNodeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ ValueTask DeleteMonitoredItemsAsync(
/// </summary>
ValueTask DeleteReferencesAsync(NodeId targetId, IList<IReference> references, CancellationToken cancellationToken = default);

/// <summary>
/// Searches the node id in all node managers,
/// returns the node state if found (and node Manager supports it), otherwise returns null.
/// </summary>
ValueTask<NodeState> FindNodeInAddressSpaceAsync(NodeId nodeId);

/// <summary>
/// Returns node handle and its node manager.
/// </summary>
Expand Down
65 changes: 50 additions & 15 deletions Libraries/Opc.Ua.Server/NodeManager/INodeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,28 @@ NodeMetadata GetPermissionMetadata(
}

/// <summary>
/// An asynchronous version of the "Call" method defined on the <see cref="INodeManager2"/> interface.
/// An interface to an object that manages a set of nodes in the address space.
/// </summary>
public interface INodeManager3 : INodeManager2
{
/// <summary>
/// Validates if the specified event monitored item has enough permissions to receive the specified event
/// </summary>
ServiceResult ValidateEventRolePermissions(
IEventMonitoredItem monitoredItem,
IFilterTarget filterTarget);

/// <summary>
/// Validates Role permissions for the specified NodeId
/// </summary>
ServiceResult ValidateRolePermissions(
OperationContext operationContext,
NodeId nodeId,
PermissionType requestedPermission);
}

/// <summary>
/// An asynchronous version of the "Call" method defined on the <see cref="INodeManager3"/> interface.
/// </summary>
public interface ICallAsyncNodeManager
{
Expand All @@ -392,7 +413,7 @@ ValueTask CallAsync(
}

/// <summary>
/// An asynchronous version of the "Read" method defined on the <see cref="INodeManager2"/> interface.
/// An asynchronous version of the "Read" method defined on the <see cref="INodeManager3"/> interface.
/// </summary>
public interface IReadAsyncNodeManager
{
Expand Down Expand Up @@ -427,7 +448,7 @@ ValueTask ReadAsync(
}

/// <summary>
/// An asynchronous version of the "Write" method defined on the <see cref="INodeManager2"/> interface.
/// An asynchronous version of the "Write" method defined on the <see cref="INodeManager3"/> interface.
/// </summary>
public interface IWriteAsyncNodeManager
{
Expand All @@ -446,7 +467,7 @@ ValueTask WriteAsync(
}

/// <summary>
/// An asynchronous version of the "HistoryRead" method defined on the <see cref="INodeManager2"/> interface.
/// An asynchronous version of the "HistoryRead" method defined on the <see cref="INodeManager3"/> interface.
/// </summary>
public interface IHistoryReadAsyncNodeManager
{
Expand All @@ -465,7 +486,7 @@ ValueTask HistoryReadAsync(
}

/// <summary>
/// An asynchronous version of the "HistoryUpdate" method defined on the <see cref="INodeManager2"/> interface.
/// An asynchronous version of the "HistoryUpdate" method defined on the <see cref="INodeManager3"/> interface.
/// </summary>
public interface IHistoryUpdateAsyncNodeManager
{
Expand All @@ -482,7 +503,7 @@ ValueTask HistoryUpdateAsync(
}

/// <summary>
/// An asynchronous version of the "ConditionRefresh" method defined on the <see cref="INodeManager2"/> interface.
/// An asynchronous version of the "ConditionRefresh" method defined on the <see cref="INodeManager3"/> interface.
/// </summary>
public interface IConditionRefreshAsyncNodeManager
{
Expand All @@ -496,7 +517,7 @@ ValueTask ConditionRefreshAsync(
}

/// <summary>
/// An asynchronous version of the "TranslateBrowsePath" method defined on the <see cref="INodeManager2"/> interface.
/// An asynchronous version of the "TranslateBrowsePath" method defined on the <see cref="INodeManager3"/> interface.
/// </summary>
public interface ITranslateBrowsePathAsyncNodeManager
{
Expand Down Expand Up @@ -527,7 +548,7 @@ ValueTask TranslateBrowsePathAsync(
}

/// <summary>
/// An asynchronous version of the "Browse" method defined on the <see cref="INodeManager2"/> interface.
/// An asynchronous version of the "Browse" method defined on the <see cref="INodeManager3"/> interface.
/// </summary>
public interface IBrowseAsyncNodeManager
{
Expand Down Expand Up @@ -557,7 +578,7 @@ ValueTask<ContinuationPoint> BrowseAsync(
}

/// <summary>
/// An asynchronous version of the "SetMonitoringMode" method defined on the <see cref="INodeManager2"/> interface.
/// An asynchronous version of the "SetMonitoringMode" method defined on the <see cref="INodeManager3"/> interface.
/// </summary>
public interface ISetMonitoringModeAsyncNodeManager
{
Expand All @@ -574,7 +595,7 @@ ValueTask SetMonitoringModeAsync(
}

/// <summary>
/// An asynchronous version of the "TransferMonitoredItems" method defined on the <see cref="INodeManager2"/> interface.
/// An asynchronous version of the "TransferMonitoredItems" method defined on the <see cref="INodeManager3"/> interface.
/// </summary>
public interface ITransferMonitoredItemsAsyncNodeManager
{
Expand All @@ -594,7 +615,7 @@ ValueTask TransferMonitoredItemsAsync(
}

/// <summary>
/// An asynchronous version of the "DeleteMonitoredItems" method defined on the <see cref="INodeManager2"/> interface.
/// An asynchronous version of the "DeleteMonitoredItems" method defined on the <see cref="INodeManager3"/> interface.
/// </summary>
public interface IDeleteMonitoredItemsAsyncNodeManager
{
Expand All @@ -610,7 +631,7 @@ ValueTask DeleteMonitoredItemsAsync(
}

/// <summary>
/// An asynchronous version of the "ModifyMonitoredItems" method defined on the <see cref="INodeManager2"/> interface.
/// An asynchronous version of the "ModifyMonitoredItems" method defined on the <see cref="INodeManager3"/> interface.
/// </summary>
public interface IModifyMonitoredItemsAsyncNodeManager
{
Expand All @@ -628,7 +649,7 @@ ValueTask ModifyMonitoredItemsAsync(
}

/// <summary>
/// An asynchronous version of the "CreateMonitoredItems" method defined on the <see cref="INodeManager2"/> interface.
/// An asynchronous version of the "CreateMonitoredItems" method defined on the <see cref="INodeManager3"/> interface.
/// </summary>
public interface ICreateMonitoredItemsAsyncNodeManager
{
Expand Down Expand Up @@ -672,11 +693,10 @@ ValueTask<IAsyncNodeManager> CreateAsync(
}

/// <summary>
/// An asynchronous verison of the <see cref="INodeManager2"/> interface.
/// An asynchronous verison of the <see cref="INodeManager3"/> interface.
/// This interface is in active development and will be extended in future releases.
/// Please use the sub interfaces to implement async support for specific service calls.
/// </summary>
[Experimental("UA_NETStandard_1")]
public interface IAsyncNodeManager :
ICallAsyncNodeManager,
IReadAsyncNodeManager,
Expand Down Expand Up @@ -847,6 +867,21 @@ ValueTask RestoreMonitoredItemsAsync(
IList<IMonitoredItem> monitoredItems,
IUserIdentity savedOwnerIdentity,
CancellationToken cancellationToken = default);

/// <summary>
/// Validates if the specified event monitored item has enough permissions to receive the specified event
/// </summary>
ValueTask <ServiceResult> ValidateEventRolePermissionsAsync(
IEventMonitoredItem monitoredItem,
IFilterTarget filterTarget);

/// <summary>
/// Validates Role permissions for the specified NodeId
/// </summary>
ValueTask<ServiceResult> ValidateRolePermissionsAsync(
OperationContext operationContext,
NodeId nodeId,
PermissionType requestedPermission);
}

/// <summary>
Expand Down
20 changes: 20 additions & 0 deletions Libraries/Opc.Ua.Server/NodeManager/MasterNodeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1794,6 +1794,26 @@ private async ValueTask<bool> UpdateReferenceDescriptionAsync(
return true;
}

/// <inheritdoc/>
public async ValueTask<NodeState> FindNodeInAddressSpaceAsync(NodeId nodeId)
{
if (nodeId.IsNull)
{
return null;
}
// search node id in all node managers
foreach (IAsyncNodeManager nodeManager in AsyncNodeManagers)
{
if ((await nodeManager.GetManagerHandleAsync(nodeId).ConfigureAwait(false))
is not NodeHandle handle)
{
continue;
}
return handle.Node;
}
return null;
}

/// <inheritdoc/>
public virtual async ValueTask<(DataValueCollection values, DiagnosticInfoCollection diagnosticInfos)> ReadAsync(
OperationContext context,
Expand Down
Loading
Loading