HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
registry.h
Go to the documentation of this file.
1 //
2 // Copyright 2018 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 
25 #ifndef PXR_USD_NDR_REGISTRY_H
26 #define PXR_USD_NDR_REGISTRY_H
27 
28 /// \file ndr/registry.h
29 
30 #include "pxr/pxr.h"
31 #include "pxr/usd/ndr/api.h"
32 #include "pxr/base/tf/weakBase.h"
33 #include "pxr/usd/ndr/declare.h"
35 #include "pxr/usd/ndr/node.h"
38 #include "pxr/usd/sdf/assetPath.h"
39 #include <map>
40 #include <mutex>
41 
43 
44 /// \class NdrRegistry
45 ///
46 /// The registry provides access to node information. "Discovery Plugins" are
47 /// responsible for finding the nodes that should be included in the registry.
48 ///
49 /// Discovery plugins are found through the plugin system. If additional
50 /// discovery plugins need to be specified, a client can pass them to
51 /// `SetExtraDiscoveryPlugins()`.
52 ///
53 /// When the registry is first told about the discovery plugins, the plugins
54 /// will be asked to discover nodes. These plugins will generate
55 /// `NdrNodeDiscoveryResult` instances, which only contain basic metadata. Once
56 /// the client asks for information that would require the node's contents to
57 /// be parsed (eg, what its inputs and outputs are), the registry will begin the
58 /// parsing process on an as-needed basis. See `NdrNodeDiscoveryResult` for the
59 /// information that can be retrieved without triggering a parse.
60 ///
61 /// Some methods in this library may allow for a "family" to be provided. A
62 /// family is simply a generic grouping which is optional.
63 ///
64 class NdrRegistry : public TfWeakBase
65 {
66 public:
67  using DiscoveryPluginRefPtrVec = NdrDiscoveryPluginRefPtrVector;
68 
69  /// Allows the client to set any additional discovery plugins that would
70  /// otherwise NOT be found through the plugin system. Runs the discovery
71  /// process for the specified plugins immediately.
72  ///
73  /// Note that this method cannot be called after any nodes in the registry
74  /// have been parsed (eg, through GetNode*()), otherwise an error will
75  /// result.
76  NDR_API
78 
79  /// Allows the client to set any additional discovery plugins that would
80  /// otherwise NOT be found through the plugin system. Runs the discovery
81  /// process for the specified plugins immediately.
82  ///
83  /// Note that this method cannot be called after any nodes in the registry
84  /// have been parsed (eg, through GetNode*()), otherwise an error will
85  /// result.
86  NDR_API
87  void SetExtraDiscoveryPlugins(const std::vector<TfType>& pluginTypes);
88 
89  /// Allows the client to explicitly set additional discovery results that
90  /// would otherwise NOT be found through the plugin system. For example
91  /// to support lazily-loaded plugins which cannot be easily discovered
92  /// in advance.
93  ///
94  /// This method will not immediately spawn a parse call which will be
95  /// deferred until a GetNode*() method is called.
96  NDR_API
97  void AddDiscoveryResult(NdrNodeDiscoveryResult&& discoveryResult);
98 
99  /// Copy version of the method above.
100  /// For performance reasons, one should prefer to use the rvalue reference
101  /// form.
102  /// \overload
103  NDR_API
104  void AddDiscoveryResult(const NdrNodeDiscoveryResult& discoveryResult);
105 
106  /// Allows the client to set any additional parser plugins that would
107  /// otherwise NOT be found through the plugin system.
108  ///
109  /// Note that this method cannot be called after any nodes in the registry
110  /// have been parsed (eg, through GetNode*()), otherwise an error will
111  /// result.
112  NDR_API
113  void SetExtraParserPlugins(const std::vector<TfType>& pluginTypes);
114 
115  /// Parses the given \p asset, constructs a NdrNode from it and adds it to
116  /// the registry.
117  ///
118  /// Nodes created from an asset using this API can be looked up by the
119  /// unique identifier and sourceType of the returned node, or by URI,
120  /// which will be set to the unresolved asset path value.
121  ///
122  /// \p metadata contains additional metadata needed for parsing and
123  /// compiling the source code in the file pointed to by \p asset correctly.
124  /// This metadata supplements the metadata available in the asset and
125  /// overrides it in cases where there are key collisions.
126  ///
127  /// \p subidentifier is optional, and it would be used to indicate a
128  /// particular definition in the asset file if the asset contains multiple
129  /// node definitions.
130  ///
131  /// \p sourceType is optional, and it is only needed to indicate a
132  /// particular type if the asset file is capable of representing a node
133  /// definition of multiple source types.
134  ///
135  /// Returns a valid node if the asset is parsed successfully using one
136  /// of the registered parser plugins.
137  NDR_API
139  const NdrTokenMap &metadata,
140  const TfToken &subIdentifier=TfToken(),
141  const TfToken &sourceType=TfToken());
142 
143  /// Parses the given \p sourceCode string, constructs a NdrNode from it and
144  /// adds it to the registry. The parser to be used is determined by the
145  /// specified \p sourceType.
146  ///
147  /// Nodes created from source code using this API can be looked up by the
148  /// unique identifier and sourceType of the returned node.
149  ///
150  /// \p metadata contains additional metadata needed for parsing and
151  /// compiling the source code correctly. This metadata supplements the
152  /// metadata available in \p sourceCode and overrides it cases where there
153  /// are key collisions.
154  ///
155  /// Returns a valid node if the given source code is parsed successfully
156  /// using the parser plugins that is registered for the specified
157  /// \p sourceType.
158  NDR_API
160  const TfToken &sourceType,
161  const NdrTokenMap &metadata);
162 
163  /// Get the locations where the registry is searching for nodes.
164  ///
165  /// Depending on which discovery plugins were used, this may include
166  /// non-filesystem paths.
167  NDR_API
168  NdrStringVec GetSearchURIs() const;
169 
170  /// Get the identifiers of all the nodes that the registry is aware of.
171  ///
172  /// This will not run the parsing plugins on the nodes that have been
173  /// discovered, so this method is relatively quick. Optionally, a "family"
174  /// name can be specified to only get the identifiers of nodes that belong
175  /// to that family and a filter can be specified to get just the default
176  /// version (the default) or all versions of the node.
177  NDR_API
179  GetNodeIdentifiers(const TfToken& family = TfToken(),
182 
183  /// Get the names of all the nodes that the registry is aware of.
184  ///
185  /// This will not run the parsing plugins on the nodes that have been
186  /// discovered, so this method is relatively quick. Optionally, a "family"
187  /// name can be specified to only get the names of nodes that belong to
188  /// that family.
189  NDR_API
190  NdrStringVec GetNodeNames(const TfToken& family = TfToken()) const;
191 
192  /// Get the node with the specified \p identifier, and an optional
193  /// \p sourceTypePriority list specifying the set of node SOURCE types (see
194  /// `NdrNode::GetSourceType()`) that should be searched.
195  ///
196  /// If no sourceTypePriority is specified, the first encountered node with
197  /// the specified identifier will be returned (first is arbitrary) if found.
198  ///
199  /// If a sourceTypePriority list is specified, then this will iterate
200  /// through each source type and try to find a node matching by identifier.
201  /// This is equivalent to calling NdrRegistry::GetNodeByIdentifierAndType
202  /// for each source type until a node is found.
203  ///
204  /// Nodes of the same identifier but different source type can exist
205  /// in the registry. If a node 'Foo' with source types 'abc' and 'xyz'
206  /// exist in the registry, and you want to make sure the 'abc' version
207  /// is fetched before the 'xyz' version, the priority list would be
208  /// specified as ['abc', 'xyz']. If the 'abc' version did not exist in
209  /// the registry, then the 'xyz' version would be returned.
210  ///
211  /// Returns `nullptr` if a node matching the arguments can't be found.
212  NDR_API
214  const NdrTokenVec& sourceTypePriority = NdrTokenVec());
215 
216  /// Get the node with the specified \p identifier and \p sourceType.
217  /// If there is no matching node for the sourceType, nullptr is returned.
218  NDR_API
220  const TfToken& sourceType);
221 
222  /// Get the node with the specified name. An optional priority list
223  /// specifies the set of node SOURCE types (\sa NdrNode::GetSourceType())
224  /// that should be searched and in what order.
225  ///
226  /// Optionally, a filter can be specified to consider just the default
227  /// versions of nodes matching \p name (the default) or all versions
228  /// of the nodes.
229  ///
230  /// \sa GetNodeByIdentifier().
231  NDR_API
233  const NdrTokenVec& sourceTypePriority = NdrTokenVec(),
235 
236  /// A convenience wrapper around \c GetNodeByName(). Instead of
237  /// providing a priority list, an exact type is specified, and
238  /// `nullptr` is returned if a node with the exact identifier and
239  /// type does not exist.
240  ///
241  /// Optionally, a filter can be specified to consider just the default
242  /// versions of nodes matching \p name (the default) or all versions
243  /// of the nodes.
244  NDR_API
246  const TfToken& sourceType,
249 
250  /// Get all nodes matching the specified identifier (multiple nodes of
251  /// the same identifier, but different source types, may exist). If no nodes
252  /// match the identifier, an empty vector is returned.
253  NDR_API
255 
256  /// Get all nodes matching the specified name. Only nodes matching the
257  /// specified name will be parsed. Optionally, a filter can be specified
258  /// to get just the default version (the default) or all versions of the
259  /// node. If no nodes match an empty vector is returned.
260  NDR_API
264 
265  /// Get all nodes from the registry, optionally restricted to the nodes
266  /// that fall under a specified family and/or the default version.
267  ///
268  /// Note that this will parse \em all nodes that the registry is aware of
269  /// (unless a family is specified), so this may take some time to run
270  /// the first time it is called.
271  NDR_API
275 
276  /// Get a sorted list of all node source types that may be present on the
277  /// nodes in the registry.
278  ///
279  /// Source types originate from the discovery process, but there is no
280  /// guarantee that the discovered source types will also have a registered
281  /// parser plugin. The actual supported source types here depend on the
282  /// parsers that are available. Also note that some parser plugins may not
283  /// advertise a source type.
284  ///
285  /// See the documentation for `NdrParserPlugin` and
286  /// `NdrNode::GetSourceType()` for more information.
287  NDR_API
289 
290 protected:
291  NdrRegistry(const NdrRegistry&) = delete;
292  NdrRegistry& operator=(const NdrRegistry&) = delete;
293 
294  NDR_API
295  NdrRegistry();
296 
297  NDR_API
298  ~NdrRegistry();
299 
300 private:
302  friend class _DiscoveryContext;
303 
304  using _TypeToParserPluginMap =
305  std::unordered_map<TfToken, NdrParserPlugin*, TfToken::HashFunctor>;
306 
307  // Node cache data structure, stored NdrNodes keyed by identifier and source
308  // type.
309  using _NodeMapKey = std::pair<NdrIdentifier, TfToken>;
310  using _NodeMap = std::unordered_map<_NodeMapKey, NdrNodeUniquePtr, TfHash>;
311 
312  // Discovery results data structure, NdrNodeDiscoveryResults multimap keyed
313  // by identifier
314  using _DiscoveryResultsByIdentifier = std::unordered_multimap<
316  using _DiscoveryResultsByIdentifierRange =
317  std::pair<_DiscoveryResultsByIdentifier::const_iterator,
318  _DiscoveryResultsByIdentifier::const_iterator>;
319 
320  // Discovery results data structure: a multimap of raw pointers to
321  // NdrNodeDiscoveryResults (i.e. pointers to the discovery results stored
322  // in a _DiscoveryResultsByIdentifier) keyed by name.
323  using _DiscoveryResultPtrsByName = std::unordered_multimap<
325  using _DiscoveryResultPtrsByNameRange =
326  std::pair<_DiscoveryResultPtrsByName::const_iterator,
327  _DiscoveryResultPtrsByName::const_iterator>;
328 
329  // The discovery result data structures are not concurrent and must be kept
330  // in sync, thus they need some locking infrastructure.
331  mutable std::mutex _discoveryResultMutex;
332 
333  // The node map is not a concurrent data structure, thus it needs some
334  // locking infrastructure.
335  mutable std::mutex _nodeMapMutex;
336 
337  // Runs each discovery plugin provided and adds the results to the
338  // internal discovery result maps
339  void _RunDiscoveryPlugins(const DiscoveryPluginRefPtrVec& discoveryPlugins);
340 
341  // Takes the discovery and puts in the maps that hold the discovery results,
342  // keeping them in sync.
343  void _AddDiscoveryResultNoLock(NdrNodeDiscoveryResult&& dr);
344 
345  // Finds and instantiates the discovery plugins
346  void _FindAndInstantiateDiscoveryPlugins();
347 
348  // Finds and instantiates the parser plugins
349  void _FindAndInstantiateParserPlugins();
350 
351  // Instantiates the specified parser plugins and adds them to
352  // the registry.
353  void _InstantiateParserPlugins(const std::set<TfType>& parserPluginTypes);
354 
355  // Parses the node for the discovery result if adding it to the node map if
356  // able and adds the discovery result to the discovery result maps. Intended
357  // for the GetNodeFromAsset and GetNodeFromSourceCode APIs which can add
358  // nodes that don't already appear in the discovery results.
359  NdrNodeConstPtr _ParseNodeFromAssetOrSourceCode(
361 
362  // Implementation helper for getting the first node of the given sourceType
363  // in the range of node discovery results for a paricular identifier.
364  NdrNodeConstPtr _GetNodeInIdentifierRangeWithSourceType(
365  _DiscoveryResultsByIdentifierRange range, const TfToken& sourceType);
366 
367  // Implementation helper for getting the first node of the given sourceType
368  // and matching the given version filter in the range of node discovery
369  // results for a paricular name.
370  NdrNodeConstPtr _GetNodeInNameRangeWithSourceType(
371  _DiscoveryResultPtrsByNameRange range, const TfToken& sourceType,
373 
374  // Thread-safe find of a node in the cache by key.
375  NdrNodeConstPtr _FindNodeInCache(const _NodeMapKey &key) const;
376 
377  // Thread-safe insertion of a node into the cache with a given key. If a
378  // node with the same key already exists in the cache, the pointer to the
379  // existing node will be returned, otherwise the pointer to pointer to the
380  // inserted node is returned.
381  NdrNodeConstPtr _InsertNodeInCache(
382  _NodeMapKey &&key, NdrNodeUniquePtr &&node);
383 
384  // Finds an existing node in the node cache for the discovery result if one
385  // exists. Otherwise it parses the new node, inserts it into the cache, and
386  // returns it. If there was an error parsing or validating the node,
387  // `nullptr` will be returned.
388  NdrNodeConstPtr _FindOrParseNodeInCache(const NdrNodeDiscoveryResult& dr);
389 
390  // Return the parser plugin for a discovery type. Returns null if no parser
391  // plugin has that discovery type.
393  _GetParserForDiscoveryType(const TfToken& discoveryType) const;
394 
395  // The discovery plugins that were found through libplug and/or provided by
396  // the client
397  DiscoveryPluginRefPtrVec _discoveryPlugins;
398 
399  // The parser plugins that have been discovered via the plugin system. Maps
400  // a discovery result's "discovery type" to a specific parser.
401  _TypeToParserPluginMap _parserPluginMap;
402 
403  // The parser plugins. This has ownership of the plugin objects.
404  std::vector<std::unique_ptr<NdrParserPlugin>> _parserPlugins;
405 
406  // The preliminary discovery results prior to parsing. These are stored
407  // in a multimap by identifier and a multimap by name. If accessing or
408  // mutating, _discoveryResultMutex should be used.
409  _DiscoveryResultsByIdentifier _discoveryResultsByIdentifier;
410  _DiscoveryResultPtrsByName _discoveryResultPtrsByName;
411 
412  // Set of all possible source types as determined by the existing discovery
413  // results. Populated along with the discovery result multimaps. If
414  // accessing or mutating, _discoveryResultMutex should be used.
415  TfToken::Set _allSourceTypes;
416 
417  // Maps a node's identifier and source type to a node instance. If accessing
418  // or mutating, _nodeMapMutex should be used.
419  _NodeMap _nodeMap;
420 };
421 
423 
424 #endif // PXR_USD_NDR_REGISTRY_H
NDR_API void AddDiscoveryResult(NdrNodeDiscoveryResult &&discoveryResult)
NDR_API NdrStringVec GetSearchURIs() const
NdrVersionFilter
Enumeration used to select nodes by version.
Definition: declare.h:203
NDR_API ~NdrRegistry()
GLenum GLint * range
Definition: glcorearb.h:1925
std::vector< TfToken > NdrTokenVec
Definition: declare.h:59
NDR_API NdrNodeConstPtr GetNodeByNameAndType(const std::string &name, const TfToken &sourceType, NdrVersionFilter filter=NdrVersionFilterDefaultOnly)
NdrNode const * NdrNodeConstPtr
Definition: declare.h:73
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
std::vector< NdrNodeConstPtr > NdrNodeConstPtrVec
Definition: declare.h:75
NdrRegistry & operator=(const NdrRegistry &)=delete
NDR_API NdrNodeConstPtr GetNodeByIdentifier(const NdrIdentifier &identifier, const NdrTokenVec &sourceTypePriority=NdrTokenVec())
friend class _DiscoveryContext
Definition: registry.h:301
NDR_API NdrRegistry()
Definition: hash.h:504
NDR_API NdrNodeConstPtr GetNodeByIdentifierAndType(const NdrIdentifier &identifier, const TfToken &sourceType)
Definition: token.h:87
std::vector< NdrIdentifier > NdrIdentifierVec
Definition: declare.h:54
NDR_API NdrNodeConstPtr GetNodeByName(const std::string &name, const NdrTokenVec &sourceTypePriority=NdrTokenVec(), NdrVersionFilter filter=NdrVersionFilterDefaultOnly)
NDR_API NdrIdentifierVec GetNodeIdentifiers(const TfToken &family=TfToken(), NdrVersionFilter filter=NdrVersionFilterDefaultOnly) const
std::vector< std::string > NdrStringVec
Definition: declare.h:79
NDR_API NdrNodeConstPtr GetNodeFromSourceCode(const std::string &sourceCode, const TfToken &sourceType, const NdrTokenMap &metadata)
NdrDiscoveryPluginRefPtrVector DiscoveryPluginRefPtrVec
Definition: registry.h:67
GLuint const GLchar * name
Definition: glcorearb.h:786
#define NDR_API
Definition: api.h:40
NDR_API NdrNodeConstPtrVec GetNodesByIdentifier(const NdrIdentifier &identifier)
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1441
NDR_API void SetExtraDiscoveryPlugins(DiscoveryPluginRefPtrVec plugins)
std::unique_ptr< NdrNode > NdrNodeUniquePtr
Definition: declare.h:74
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
NDR_API NdrStringVec GetNodeNames(const TfToken &family=TfToken()) const
std::unordered_map< TfToken, std::string, TfToken::HashFunctor > NdrTokenMap
Definition: declare.h:61
NDR_API void SetExtraParserPlugins(const std::vector< TfType > &pluginTypes)
NDR_API NdrNodeConstPtr GetNodeFromAsset(const SdfAssetPath &asset, const NdrTokenMap &metadata, const TfToken &subIdentifier=TfToken(), const TfToken &sourceType=TfToken())
std::set< TfToken, TfTokenFastArbitraryLessThan > Set
Definition: token.h:183
NDR_API NdrNodeConstPtrVec GetNodesByName(const std::string &name, NdrVersionFilter filter=NdrVersionFilterDefaultOnly)
NDR_API NdrNodeConstPtrVec GetNodesByFamily(const TfToken &family=TfToken(), NdrVersionFilter filter=NdrVersionFilterDefaultOnly)
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glcorearb.h:1297
NDR_API NdrTokenVec GetAllNodeSourceTypes() const