The table of all reference types known to the server.
This class is thread safe.
상속: IDisposable
예제 #1
0
        /// <summary>
        /// Restores a continuation point for a session.
        /// </summary>
        /// <remarks>
        /// The caller is responsible for disposing the continuation point returned.
        /// </remarks>
        public ContinuationPoint RestoreContinuationPoint(byte[] continuationPoint)
        {
            lock (m_lock)
            {
                if (m_browseContinuationPoints == null)
                {
                    return(null);
                }

                if (continuationPoint == null || continuationPoint.Length != 16)
                {
                    return(null);
                }

                Guid id = new Guid(continuationPoint);

                for (int ii = 0; ii < m_browseContinuationPoints.Count; ii++)
                {
                    if (m_browseContinuationPoints[ii].Id == id)
                    {
                        ContinuationPoint cp = m_browseContinuationPoints[ii];
                        m_browseContinuationPoints.RemoveAt(ii);
                        return(cp);
                    }
                }

                return(null);
            }
        }
예제 #2
0
        /// <summary>
        /// Saves a continuation point for a session.
        /// </summary>
        /// <remarks>
        /// If the session has too many continuation points the oldest one is dropped.
        /// </remarks>
        public void SaveContinuationPoint(ContinuationPoint continuationPoint)
        {
            if (continuationPoint == null)
            {
                throw new ArgumentNullException("continuationPoint");
            }

            lock (m_lock)
            {
                if (m_browseContinuationPoints == null)
                {
                    m_browseContinuationPoints = new List <ContinuationPoint>();
                }

                // remove the first continuation point if too many points.
                while (m_browseContinuationPoints.Count > m_maxBrowseContinuationPoints)
                {
                    ContinuationPoint cp = m_browseContinuationPoints[0];
                    m_browseContinuationPoints.RemoveAt(0);
                    Utils.SilentDispose(cp);
                }

                // add to end of list.
                m_browseContinuationPoints.Add(continuationPoint);
            }
        }
        /// <summary>
        /// Browses the references from a node managed by the node manager.
        /// </summary>
        /// <remarks>
        /// The continuation point is created for every browse operation and contains the browse parameters.
        /// The node manager can store its state information in the Data and Index properties.
        /// </remarks>
        public virtual void Browse(
            OperationContext            context, 
            ref ContinuationPoint       continuationPoint, 
            IList<ReferenceDescription> references)
        {
            if (continuationPoint == null) throw new ArgumentNullException("continuationPoint");
            if (references == null) throw new ArgumentNullException("references");

            // check for view.
            if (!ViewDescription.IsDefault(continuationPoint.View))
            {
                throw new ServiceResultException(StatusCodes.BadViewIdUnknown);
            }

            ServerSystemContext systemContext = m_systemContext.Copy(context);

            lock (Lock)
            {
                // verify that the node exists.
                NodeState source = IsHandleInNamespace(continuationPoint.NodeToBrowse);

                if (source == null)
                {
                    throw new ServiceResultException(StatusCodes.BadNodeIdUnknown);
                }

                // validate node.
                if (!ValidateNode(systemContext, source))
                {
                    throw new ServiceResultException(StatusCodes.BadNodeIdUnknown);
                }

                // check for previous continuation point.
                INodeBrowser browser = continuationPoint.Data as INodeBrowser;

                // fetch list of references.
                if (browser == null)
                {
                    // create a new browser.
                    browser = source.CreateBrowser(
                        systemContext,
                        continuationPoint.View,
                        continuationPoint.ReferenceTypeId,
                        continuationPoint.IncludeSubtypes,
                        continuationPoint.BrowseDirection,
                        null,
                        null,
                        false);
                }

                // apply filters to references.
                for (IReference reference = browser.Next(); reference != null; reference = browser.Next())
                {
                    // create the type definition reference.        
                    ReferenceDescription description = GetReferenceDescription(context, reference, continuationPoint);

                    if (description == null)
                    {
                        continue;
                    }

                    // check if limit reached.
                    if (continuationPoint.MaxResultsToReturn != 0 && references.Count >= continuationPoint.MaxResultsToReturn)
                    {
                        browser.Push(reference);
                        continuationPoint.Data = browser;
                        return;
                    }

                    references.Add(description);
                }

                // release the continuation point if all done.
                continuationPoint.Dispose();
                continuationPoint = null;
            }
        }
        /// <summary>
        /// Returns the references for the node that meets the criteria specified.
        /// </summary>
        private ReferenceDescription GetReferenceDescription(
            OperationContext context,
            IReference reference,
            ContinuationPoint continuationPoint)
        {
            // create the type definition reference.        
            ReferenceDescription description = new ReferenceDescription();

            description.NodeId = reference.TargetId;
            description.SetReferenceType(continuationPoint.ResultMask, reference.ReferenceTypeId, !reference.IsInverse);

            // do not cache target parameters for remote nodes.
            if (reference.TargetId.IsAbsolute)
            {
                // only return remote references if no node class filter is specified.
                if (continuationPoint.NodeClassMask != 0)
                {
                    return null;
                }

                return description;
            }

            NodeState target = null;

            // check for local reference.
            NodeStateReference referenceInfo = reference as NodeStateReference;

            if (referenceInfo != null)
            {
                target = referenceInfo.Target;
            }

            // check for internal reference.
            if (target == null)
            {
                NodeId targetId = (NodeId)reference.TargetId;

                if (IsNodeIdInNamespace(targetId))
                {
                    if (!PredefinedNodes.TryGetValue(targetId, out target))
                    {
                        target = null;
                    }
                }
            }

            // the target may be a reference to a node in another node manager. In these cases
            // the target attributes must be fetched by the caller. The Unfiltered flag tells the
            // caller to do that.
            if (target == null)
            {
                description.Unfiltered = true;
                return description;
            }

            // apply node class filter.
            if (continuationPoint.NodeClassMask != 0 && ((continuationPoint.NodeClassMask & (uint)target.NodeClass) == 0))
            {
                return null;
            }

            NodeId typeDefinition = null;

            BaseInstanceState instance = target as BaseInstanceState;

            if (instance != null)
            {
                typeDefinition = instance.TypeDefinitionId;
            }

            // set target attributes.
            description.SetTargetAttributes(
                continuationPoint.ResultMask,
                target.NodeClass,
                target.BrowseName,
                target.DisplayName,
                typeDefinition);

            return description;
        }
예제 #5
0
        /// <summary>
        /// Checks if the reference is in the view.
        /// </summary>
        protected override bool IsReferenceInView(ServerSystemContext context, ContinuationPoint continuationPoint, IReference reference)
        {
            if (continuationPoint.View != null)
            {
                // guard against absolute node ids.
                if (reference.TargetId.IsAbsolute)
                {
                    return true;
                }

                // find the node.
                NodeState node = FindPredefinedNode((NodeId)reference.TargetId, typeof(NodeState));

                if (node != null)
                {
                    return IsNodeInView(context, continuationPoint, node);
                }
            }

            return true;
        }
예제 #6
0
        /// <summary>
        /// Checks if the node is in the view.
        /// </summary>
        protected override bool IsNodeInView(ServerSystemContext context, ContinuationPoint continuationPoint, NodeState node)
        {
            if (continuationPoint.View != null)
            {
                if (continuationPoint.View.ViewId == new NodeId(Quickstarts.Views.Views.Engineering, NamespaceIndex))
                {
                    // suppress operations properties.
                    if (node != null && node.BrowseName.NamespaceIndex == NamespaceIndexes[2])
                    {
                        return false;
                    }
                }

                if (continuationPoint.View.ViewId == new NodeId(Quickstarts.Views.Views.Operations, NamespaceIndex))
                {
                    // suppress engineering properties.
                    if (node != null && node.BrowseName.NamespaceIndex == NamespaceIndexes[1])
                    {
                        return false;
                    }
                }
            }

            return true;
        }
        /// <summary>
        /// Returns the references for the node that meets the criteria specified.
        /// </summary>
        protected virtual ReferenceDescription GetReferenceDescription(
            ServerSystemContext context,
            Dictionary<NodeId,NodeState> cache,
            IReference reference,
            ContinuationPoint continuationPoint)
        {
            ServerSystemContext systemContext = m_systemContext.Copy(context);

            // create the type definition reference.        
            ReferenceDescription description = new ReferenceDescription();

            description.NodeId = reference.TargetId;
            description.SetReferenceType(continuationPoint.ResultMask, reference.ReferenceTypeId, !reference.IsInverse);
            
            // check if reference is in the view.
            if (!IsReferenceInView(context, continuationPoint, reference))
            {
                return null;
            }

            // do not cache target parameters for remote nodes.
            if (reference.TargetId.IsAbsolute)
            {
                // only return remote references if no node class filter is specified.
                if (continuationPoint.NodeClassMask != 0)
                {
                    return null;
                }

                return description;
            }

            NodeState target = null;

            // check for local reference.
            NodeStateReference referenceInfo = reference as NodeStateReference;

            if (referenceInfo != null)
            {
                target = referenceInfo.Target;
            }

            // check for internal reference.
            if (target == null)
            {
                NodeHandle handle = GetManagerHandle(context, (NodeId)reference.TargetId, null) as NodeHandle;
                
                if (handle != null)
                {
                    target = ValidateNode(context, handle, null);
                }
            }

            // the target may be a reference to a node in another node manager. In these cases
            // the target attributes must be fetched by the caller. The Unfiltered flag tells the
            // caller to do that.
            if (target == null)
            {
                description.Unfiltered = true;
                return description;
            }

            // apply node class filter.
            if (continuationPoint.NodeClassMask != 0 && ((continuationPoint.NodeClassMask & (uint)target.NodeClass) == 0))
            {
                return null;
            }

            // check if target is in the view.
            if (!IsNodeInView(context, continuationPoint, target))
            {
                return null;
            }

            // look up the type definition.
            NodeId typeDefinition = null;

            BaseInstanceState instance = target as BaseInstanceState;

            if (instance != null)
            {
                typeDefinition = instance.TypeDefinitionId;
            }

            // set target attributes.
            description.SetTargetAttributes(
                continuationPoint.ResultMask,
                target.NodeClass,
                target.BrowseName,
                target.DisplayName,
                typeDefinition);

            return description;
        }
 /// <summary>
 /// Checks if the reference is in the view.
 /// </summary>
 protected virtual bool IsReferenceInView(ServerSystemContext context, ContinuationPoint continuationPoint, IReference reference)
 {
     return true;
 }
 /// <summary>
 /// Checks if the node is in the view.
 /// </summary>
 protected virtual bool IsNodeInView(ServerSystemContext context, ContinuationPoint continuationPoint, NodeState node)
 {
     return true;
 }
예제 #10
0
        /// <summary>
        /// Browses the references from a node managed by the node manager.
        /// </summary>
        /// <remarks>
        /// The continuation point is created for every browse operation and contains the browse parameters.
        /// The node manager can store its state information in the Data and Index properties.
        /// </remarks>
        public virtual void Browse(
            OperationContext            context, 
            ref ContinuationPoint       continuationPoint, 
            IList<ReferenceDescription> references)
        {            
            if (continuationPoint == null) throw new ArgumentNullException("continuationPoint");
            if (references == null) throw new ArgumentNullException("references");
            
            ServerSystemContext systemContext = m_systemContext.Copy(context);

            // check for valid view.
            ValidateViewDescription(systemContext, continuationPoint.View);
            
            INodeBrowser browser = null;

            lock (Lock)
            {
                // check for valid handle.
                NodeHandle handle = IsHandleInNamespace(continuationPoint.NodeToBrowse);

                if (handle == null)
                {
                    throw new ServiceResultException(StatusCodes.BadNodeIdUnknown);             
                }
                
                // validate node.
                NodeState source = ValidateNode(systemContext, handle, null);

                if (source == null)
                {
                    throw new ServiceResultException(StatusCodes.BadNodeIdUnknown);
                }

                // check if node is in the view.
                if (!IsNodeInView(systemContext, continuationPoint, source))
                {
                    throw new ServiceResultException(StatusCodes.BadNodeNotInView);
                }                

                // check for previous continuation point.
                browser = continuationPoint.Data as INodeBrowser;

                // fetch list of references.
                if (browser == null)
                {
                    // create a new browser.
                    continuationPoint.Data = browser = source.CreateBrowser(
                        systemContext,
                        continuationPoint.View,
                        continuationPoint.ReferenceTypeId,
                        continuationPoint.IncludeSubtypes,
                        continuationPoint.BrowseDirection,
                        null,
                        null,
                        false);
                }
            }

            // prevent multiple access the browser object.
            lock (browser)
            {
                // apply filters to references.
                Dictionary<NodeId, NodeState> cache = new Dictionary<NodeId, NodeState>();

                for (IReference reference = browser.Next(); reference != null; reference = browser.Next())
                {
                    // create the type definition reference.        
                    ReferenceDescription description = GetReferenceDescription(systemContext, cache, reference, continuationPoint);

                    if (description == null)
                    {
                        continue;
                    }

                    // check if limit reached.
                    if (continuationPoint.MaxResultsToReturn != 0 && references.Count >= continuationPoint.MaxResultsToReturn)
                    {
                        browser.Push(reference);
                        return;
                    }

                    references.Add(description);
                }

                // release the continuation point if all done.
                continuationPoint.Dispose();
                continuationPoint = null;
            }
        }
        /// <summary>
        /// Saves a continuation point for a session.
        /// </summary>
        /// <remarks>
        /// If the session has too many continuation points the oldest one is dropped.
        /// </remarks>
        public void SaveContinuationPoint(ContinuationPoint continuationPoint)
        {
            if (continuationPoint == null) throw new ArgumentNullException("continuationPoint");

            lock (m_lock)
            {
                if (m_browseContinuationPoints == null)
                {
                    m_browseContinuationPoints = new List<ContinuationPoint>();
                }

                // remove the first continuation point if too many points.
                while (m_browseContinuationPoints.Count > m_maxBrowseContinuationPoints)
                {
                    ContinuationPoint cp = m_browseContinuationPoints[0];
                    m_browseContinuationPoints.RemoveAt(0);
                    Utils.SilentDispose(cp);
                }

                // add to end of list.
                m_browseContinuationPoints.Add(continuationPoint);
            }
        }
        /// <see cref="INodeManager.Browse" />
        public void Browse(
            OperationContext            context,
            ref ContinuationPoint       continuationPoint,
            IList<ReferenceDescription> references)
        {              
            if (context == null) throw new ArgumentNullException("context");
            if (continuationPoint == null) throw new ArgumentNullException("continuationPoint");
            if (references == null) throw new ArgumentNullException("references");
            
            // check for valid handle.
            ILocalNode source = continuationPoint.NodeToBrowse as ILocalNode;

            if (source == null)
            {
                throw new ServiceResultException(StatusCodes.BadNodeIdUnknown);
            }
            
            // check for view.
            if (!ViewDescription.IsDefault(continuationPoint.View))
            {
                throw new ServiceResultException(StatusCodes.BadViewIdUnknown);
            }

            lock (m_lock)
            {
                // construct list of references.
                uint maxResultsToReturn = continuationPoint.MaxResultsToReturn;

                // get previous enumerator.
                IEnumerator<IReference> enumerator = continuationPoint.Data as IEnumerator<IReference>;
            
                // fetch a snapshot all references for node.
                if (enumerator == null)
                {
                    List<IReference> copy = new List<IReference>(source.References);
                    enumerator = copy.GetEnumerator();
                    enumerator.MoveNext();
                }

                do
                {
                    IReference reference = enumerator.Current;

                    // silently ignore bad values.
                    if (reference == null || NodeId.IsNull(reference.ReferenceTypeId) || NodeId.IsNull(reference.TargetId))
                    {
                        continue;
                    }

                    // apply browse filters.
                    bool include = ApplyBrowseFilters(
                        reference,
                        continuationPoint.BrowseDirection,
                        continuationPoint.ReferenceTypeId,
                        continuationPoint.IncludeSubtypes);

                    if (include)
                    {                 
                        ReferenceDescription description = new ReferenceDescription();
                        
                        description.NodeId = reference.TargetId;
                        description.SetReferenceType(continuationPoint.ResultMask, reference.ReferenceTypeId, !reference.IsInverse);

                        // only fetch the metadata if it is requested.
                        if (continuationPoint.TargetAttributesRequired)
                        {                        
                            // get the metadata for the node.
                            NodeMetadata metadata = GetNodeMetadata(context, GetManagerHandle(reference.TargetId), continuationPoint.ResultMask);

                            // update description with local node metadata.
                            if (metadata != null)
                            {
                                description.SetTargetAttributes(
                                    continuationPoint.ResultMask,
                                    metadata.NodeClass,
                                    metadata.BrowseName,
                                    metadata.DisplayName,
                                    metadata.TypeDefinition);

                                // check node class mask.
                                if (!CheckNodeClassMask(continuationPoint.NodeClassMask, description.NodeClass))
                                {
                                    continue;
                                }
                            }

                            // any target that is not remote must be owned by another node manager.
                            else if (!reference.TargetId.IsAbsolute)
                            {
                                description.Unfiltered = true;
                            }
                        }

                        // add reference to list.
                        references.Add(description);

                        // construct continuation point if max results reached.
                        if (maxResultsToReturn > 0 && references.Count >= maxResultsToReturn)
                        { 
                            continuationPoint.Index = 0;
                            continuationPoint.Data  = enumerator;
                            enumerator.MoveNext();
                            return;
                        }
                    }
                }
                while (enumerator.MoveNext());
                
                // nothing more to browse if it exits from the loop normally.
                continuationPoint.Dispose();
                continuationPoint = null;
            }
        }
예제 #13
0
        /// <summary>
        /// Loops until browse is complete for max results reached.
        /// </summary>
        protected ServiceResult FetchReferences(
            OperationContext                   context,
            bool                               assignContinuationPoint,
            ref ContinuationPoint              cp, 
            ref ReferenceDescriptionCollection references)
        {
            Debug.Assert(context != null);
            Debug.Assert(cp != null);
            Debug.Assert(references != null);

            INodeManager nodeManager = cp.Manager;
            NodeClass nodeClassMask = (NodeClass)cp.NodeClassMask;
            BrowseResultMask resultMask = cp.ResultMask;

            // loop until browse is complete or max results.
            while (cp != null)
            {
                // fetch next batch.
                nodeManager.Browse(context, ref cp, references);
                
                ReferenceDescriptionCollection referencesToKeep = new ReferenceDescriptionCollection(references.Count);

                // check for incomplete reference descriptions.
                for (int ii = 0; ii < references.Count; ii++)
                {
                    ReferenceDescription reference = references[ii];
                    
                    // check if filtering must be applied.
                    if (reference.Unfiltered)
                    {                   
                        // ignore unknown external references.
                        if (reference.NodeId.IsAbsolute)
                        {
                            continue;
                        }

                        // update the description.
                        bool include = UpdateReferenceDescription(
                            context,
                            (NodeId)reference.NodeId,
                            nodeClassMask,
                            resultMask,
                            reference);

                        if (!include)
                        {
                            continue;
                        }
                    }

                    // add to list.
                    referencesToKeep.Add(reference);
                }

                // replace list.
                references = referencesToKeep;

                // check if browse limit reached.
                if (cp != null && references.Count >= cp.MaxResultsToReturn)
                {
                    if (!assignContinuationPoint)
                    {
                        return StatusCodes.BadNoContinuationPoints;
                    }

                    cp.Id = Guid.NewGuid();
                    context.Session.SaveContinuationPoint(cp);
                    break;
                }
            }

            // all is good.
            return ServiceResult.Good;
        }
예제 #14
0
        /// <summary>
        /// Returns the set of references that meet the filter criteria.
        /// </summary>
        private ServiceResult Browse(
            OperationContext  context,
            ViewDescription   view,
            uint              maxReferencesPerNode,
            bool              assignContinuationPoint,
            BrowseDescription nodeToBrowse,
            BrowseResult      result)
        {
            Debug.Assert(context != null);
            Debug.Assert(nodeToBrowse != null);
            Debug.Assert(result != null);

            // find node manager that owns the node.
            INodeManager nodeManager = null; 
               
            object handle = GetManagerHandle(nodeToBrowse.NodeId, out nodeManager);

            if (handle == null)
            {
                return StatusCodes.BadNodeIdUnknown;
            }

            if (!NodeId.IsNull(nodeToBrowse.ReferenceTypeId) && !m_server.TypeTree.IsKnown(nodeToBrowse.ReferenceTypeId))
            {
                return StatusCodes.BadReferenceTypeIdInvalid;
            }

            if (nodeToBrowse.BrowseDirection < BrowseDirection.Forward || nodeToBrowse.BrowseDirection > BrowseDirection.Both)
            {
                return StatusCodes.BadBrowseDirectionInvalid;
            }
        
            // create a continuation point.
            ContinuationPoint cp = new ContinuationPoint();

            cp.Manager            = nodeManager;
            cp.View               = view;
            cp.NodeToBrowse       = handle;
            cp.MaxResultsToReturn = maxReferencesPerNode;
            cp.BrowseDirection    = nodeToBrowse.BrowseDirection;
            cp.ReferenceTypeId    = nodeToBrowse.ReferenceTypeId;
            cp.IncludeSubtypes    = nodeToBrowse.IncludeSubtypes;
            cp.NodeClassMask      = nodeToBrowse.NodeClassMask;
            cp.ResultMask         = (BrowseResultMask)nodeToBrowse.ResultMask;
            cp.Index              = 0;
            cp.Data               = null;

            // check if reference type left unspecified.
            if (NodeId.IsNull(cp.ReferenceTypeId))
            {
                cp.ReferenceTypeId = ReferenceTypeIds.References;
                cp.IncludeSubtypes = true;
            }

            // loop until browse is complete or max results.
            ReferenceDescriptionCollection references = result.References;
            ServiceResult error = FetchReferences(context, assignContinuationPoint, ref cp, ref references);
            result.References = references;

            // save continuation point.
            if (cp != null)
            {
                result.StatusCode = StatusCodes.Good;
                result.ContinuationPoint = cp.Id.ToByteArray();
            }

            // all is good.
            return error;
        }
        /// <summary>
        /// Checks if the node is in the view.
        /// </summary>
        protected virtual bool IsNodeInView(ServerSystemContext context, ContinuationPoint continuationPoint, NodeState node)
        {
            if (continuationPoint == null || ViewDescription.IsDefault(continuationPoint.View))
            {
                return true;
            }

            return IsNodeInView(context, continuationPoint.View.ViewId, node);
        }