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 set any additional parser plugins that would
90  /// otherwise NOT be found through the plugin system.
91  ///
92  /// Note that this method cannot be called after any nodes in the registry
93  /// have been parsed (eg, through GetNode*()), otherwise an error will
94  /// result.
95  NDR_API
96  void SetExtraParserPlugins(const std::vector<TfType>& pluginTypes);
97 
98  /// Parses the given \p asset, constructs a NdrNode from it and adds it to
99  /// the registry.
100  ///
101  /// Nodes created from an asset using this API can be looked up by the
102  /// unique identifier and sourceType of the returned node, or by URI,
103  /// which will be set to the unresolved asset path value.
104  ///
105  /// \p metadata contains additional metadata needed for parsing and
106  /// compiling the source code in the file pointed to by \p asset correctly.
107  /// This metadata supplements the metadata available in the asset and
108  /// overrides it in cases where there are key collisions.
109  ///
110  /// \p subidentifier is optional, and it would be used to indicate a
111  /// particular definition in the asset file if the asset contains multiple
112  /// node definitions.
113  ///
114  /// \p sourceType is optional, and it is only needed to indicate a
115  /// particular type if the asset file is capable of representing a node
116  /// definition of multiple source types.
117  ///
118  /// Returns a valid node if the asset is parsed successfully using one
119  /// of the registered parser plugins.
120  NDR_API
122  const NdrTokenMap &metadata,
123  const TfToken &subIdentifier=TfToken(),
124  const TfToken &sourceType=TfToken());
125 
126  /// Parses the given \p sourceCode string, constructs a NdrNode from it and
127  /// adds it to the registry. The parser to be used is determined by the
128  /// specified \p sourceType.
129  ///
130  /// Nodes created from source code using this API can be looked up by the
131  /// unique identifier and sourceType of the returned node.
132  ///
133  /// \p metadata contains additional metadata needed for parsing and
134  /// compiling the source code correctly. This metadata supplements the
135  /// metadata available in \p sourceCode and overrides it cases where there
136  /// are key collisions.
137  ///
138  /// Returns a valid node if the given source code is parsed successfully
139  /// using the parser plugins that is registered for the specified
140  /// \p sourceType.
141  NDR_API
143  const TfToken &sourceType,
144  const NdrTokenMap &metadata);
145 
146  /// Get the locations where the registry is searching for nodes.
147  ///
148  /// Depending on which discovery plugins were used, this may include
149  /// non-filesystem paths.
150  NDR_API
151  NdrStringVec GetSearchURIs() const;
152 
153  /// Get the identifiers of all the nodes that the registry is aware of.
154  ///
155  /// This will not run the parsing plugins on the nodes that have been
156  /// discovered, so this method is relatively quick. Optionally, a "family"
157  /// name can be specified to only get the identifiers of nodes that belong
158  /// to that family and a filter can be specified to get just the default
159  /// version (the default) or all versions of the node.
160  NDR_API
162  GetNodeIdentifiers(const TfToken& family = TfToken(),
165 
166  /// Get the names of all the nodes that the registry is aware of.
167  ///
168  /// This will not run the parsing plugins on the nodes that have been
169  /// discovered, so this method is relatively quick. Optionally, a "family"
170  /// name can be specified to only get the names of nodes that belong to
171  /// that family.
172  NDR_API
173  NdrStringVec GetNodeNames(const TfToken& family = TfToken()) const;
174 
175  /// Get the node with the specified \p identifier, and an optional
176  /// \p sourceTypePriority list specifying the set of node SOURCE types (see
177  /// `NdrNode::GetSourceType()`) that should be searched.
178  ///
179  /// If no sourceTypePriority is specified, the first encountered node with
180  /// the specified identifier will be returned (first is arbitrary) if found.
181  ///
182  /// If a sourceTypePriority list is specified, then this will iterate
183  /// through each source type and try to find a node matching by identifier.
184  /// This is equivalent to calling NdrRegistry::GetNodeByIdentifierAndType
185  /// for each source type until a node is found.
186  ///
187  /// Nodes of the same identifier but different source type can exist
188  /// in the registry. If a node 'Foo' with source types 'abc' and 'xyz'
189  /// exist in the registry, and you want to make sure the 'abc' version
190  /// is fetched before the 'xyz' version, the priority list would be
191  /// specified as ['abc', 'xyz']. If the 'abc' version did not exist in
192  /// the registry, then the 'xyz' version would be returned.
193  ///
194  /// Returns `nullptr` if a node matching the arguments can't be found.
195  NDR_API
197  const NdrTokenVec& sourceTypePriority = NdrTokenVec());
198 
199  /// Get the node with the specified \p identifier and \p sourceType.
200  /// If there is no matching node for the sourceType, nullptr is returned.
201  NDR_API
203  const TfToken& sourceType);
204 
205  /// Get the node with the specified name. An optional priority list
206  /// specifies the set of node SOURCE types (\sa NdrNode::GetSourceType())
207  /// that should be searched and in what order.
208  ///
209  /// Optionally, a filter can be specified to consider just the default
210  /// versions of nodes matching \p name (the default) or all versions
211  /// of the nodes.
212  ///
213  /// \sa GetNodeByIdentifier().
214  NDR_API
216  const NdrTokenVec& sourceTypePriority = NdrTokenVec(),
218 
219  /// A convenience wrapper around \c GetNodeByName(). Instead of
220  /// providing a priority list, an exact type is specified, and
221  /// `nullptr` is returned if a node with the exact identifier and
222  /// type does not exist.
223  ///
224  /// Optionally, a filter can be specified to consider just the default
225  /// versions of nodes matching \p name (the default) or all versions
226  /// of the nodes.
227  NDR_API
229  const TfToken& sourceType,
232 
233  /// Get all nodes matching the specified identifier (multiple nodes of
234  /// the same identifier, but different source types, may exist). If no nodes
235  /// match the identifier, an empty vector is returned.
236  NDR_API
238 
239  /// Get all nodes matching the specified name. Only nodes matching the
240  /// specified name will be parsed. Optionally, a filter can be specified
241  /// to get just the default version (the default) or all versions of the
242  /// node. If no nodes match an empty vector is returned.
243  NDR_API
247 
248  /// Get all nodes from the registry, optionally restricted to the nodes
249  /// that fall under a specified family and/or the default version.
250  ///
251  /// Note that this will parse \em all nodes that the registry is aware of
252  /// (unless a family is specified), so this may take some time to run
253  /// the first time it is called.
254  NDR_API
258 
259  /// Get a sorted list of all node source types that may be present on the
260  /// nodes in the registry.
261  ///
262  /// Source types originate from the discovery process, but there is no
263  /// guarantee that the discovered source types will also have a registered
264  /// parser plugin. The actual supported source types here depend on the
265  /// parsers that are available. Also note that some parser plugins may not
266  /// advertise a source type.
267  ///
268  /// See the documentation for `NdrParserPlugin` and
269  /// `NdrNode::GetSourceType()` for more information.
270  NDR_API
272 
273 protected:
274  NdrRegistry(const NdrRegistry&) = delete;
275  NdrRegistry& operator=(const NdrRegistry&) = delete;
276 
277  NDR_API
278  NdrRegistry();
279 
280  NDR_API
281  ~NdrRegistry();
282 
283 private:
285  friend class _DiscoveryContext;
286 
287  using _TypeToParserPluginMap =
288  std::unordered_map<TfToken, NdrParserPlugin*, TfToken::HashFunctor>;
289 
290  // Node cache data structure, stored NdrNodes keyed by identifier and source
291  // type.
292  using _NodeMapKey = std::pair<NdrIdentifier, TfToken>;
293  using _NodeMap = std::unordered_map<_NodeMapKey, NdrNodeUniquePtr, TfHash>;
294 
295  // Discovery results data structure, NdrNodeDiscoveryResults multimap keyed
296  // by identifier
297  using _DiscoveryResultsByIdentifier = std::unordered_multimap<
299  using _DiscoveryResultsByIdentifierRange =
300  std::pair<_DiscoveryResultsByIdentifier::const_iterator,
301  _DiscoveryResultsByIdentifier::const_iterator>;
302 
303  // Discovery results data structure: a multimap of raw pointers to
304  // NdrNodeDiscoveryResults (i.e. pointers to the discovery results stored
305  // in a _DiscoveryResultsByIdentifier) keyed by name.
306  using _DiscoveryResultPtrsByName = std::unordered_multimap<
308  using _DiscoveryResultPtrsByNameRange =
309  std::pair<_DiscoveryResultPtrsByName::const_iterator,
310  _DiscoveryResultPtrsByName::const_iterator>;
311 
312  // The discovery result data structures are not concurrent and must be kept
313  // in sync, thus they need some locking infrastructure.
314  mutable std::mutex _discoveryResultMutex;
315 
316  // The node map is not a concurrent data structure, thus it needs some
317  // locking infrastructure.
318  mutable std::mutex _nodeMapMutex;
319 
320  // Runs each discovery plugin provided and adds the results to the
321  // internal discovery result maps
322  void _RunDiscoveryPlugins(const DiscoveryPluginRefPtrVec& discoveryPlugins);
323 
324  // Takes the discovery and puts in the maps that hold the discovery results,
325  // keeping them in sync.
326  void _AddDiscoveryResultNoLock(NdrNodeDiscoveryResult&& dr);
327 
328  // Finds and instantiates the discovery plugins
329  void _FindAndInstantiateDiscoveryPlugins();
330 
331  // Finds and instantiates the parser plugins
332  void _FindAndInstantiateParserPlugins();
333 
334  // Instantiates the specified parser plugins and adds them to
335  // the registry.
336  void _InstantiateParserPlugins(const std::set<TfType>& parserPluginTypes);
337 
338  // Parses the node for the discovery result if adding it to the node map if
339  // able and adds the discovery result to the discovery result maps. Intended
340  // for the GetNodeFromAsset and GetNodeFromSourceCode APIs which can add
341  // nodes that don't already appear in the discovery results.
342  NdrNodeConstPtr _ParseNodeFromAssetOrSourceCode(
344 
345  // Implementation helper for getting the first node of the given sourceType
346  // in the range of node discovery results for a paricular identifier.
347  NdrNodeConstPtr _GetNodeInIdentifierRangeWithSourceType(
348  _DiscoveryResultsByIdentifierRange range, const TfToken& sourceType);
349 
350  // Implementation helper for getting the first node of the given sourceType
351  // and matching the given version filter in the range of node discovery
352  // results for a paricular name.
353  NdrNodeConstPtr _GetNodeInNameRangeWithSourceType(
354  _DiscoveryResultPtrsByNameRange range, const TfToken& sourceType,
356 
357  // Thread-safe find of a node in the cache by key.
358  NdrNodeConstPtr _FindNodeInCache(const _NodeMapKey &key) const;
359 
360  // Thread-safe insertion of a node into the cache with a given key. If a
361  // node with the same key already exists in the cache, the pointer to the
362  // existing node will be returned, otherwise the pointer to pointer to the
363  // inserted node is returned.
364  NdrNodeConstPtr _InsertNodeInCache(
365  _NodeMapKey &&key, NdrNodeUniquePtr &&node);
366 
367  // Finds an existing node in the node cache for the discovery result if one
368  // exists. Otherwise it parses the new node, inserts it into the cache, and
369  // returns it. If there was an error parsing or validating the node,
370  // `nullptr` will be returned.
371  NdrNodeConstPtr _FindOrParseNodeInCache(const NdrNodeDiscoveryResult& dr);
372 
373  // Return the parser plugin for a discovery type. Returns null if no parser
374  // plugin has that discovery type.
376  _GetParserForDiscoveryType(const TfToken& discoveryType) const;
377 
378  // The discovery plugins that were found through libplug and/or provided by
379  // the client
380  DiscoveryPluginRefPtrVec _discoveryPlugins;
381 
382  // The parser plugins that have been discovered via the plugin system. Maps
383  // a discovery result's "discovery type" to a specific parser.
384  _TypeToParserPluginMap _parserPluginMap;
385 
386  // The parser plugins. This has ownership of the plugin objects.
387  std::vector<std::unique_ptr<NdrParserPlugin>> _parserPlugins;
388 
389  // The preliminary discovery results prior to parsing. These are stored
390  // in a multimap by identifier and a multimap by name. If accessing or
391  // mutating, _discoveryResultMutex should be used.
392  _DiscoveryResultsByIdentifier _discoveryResultsByIdentifier;
393  _DiscoveryResultPtrsByName _discoveryResultPtrsByName;
394 
395  // Set of all possible source types as determined by the existing discovery
396  // results. Populated along with the discovery result multimaps. If
397  // accessing or mutating, _discoveryResultMutex should be used.
398  TfToken::Set _allSourceTypes;
399 
400  // Maps a node's identifier and source type to a node instance. If accessing
401  // or mutating, _nodeMapMutex should be used.
402  _NodeMap _nodeMap;
403 };
404 
406 
407 #endif // PXR_USD_NDR_REGISTRY_H
NDR_API NdrStringVec GetSearchURIs() const
NdrVersionFilter
Enumeration used to select nodes by version.
Definition: declare.h:203
NDR_API ~NdrRegistry()
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
std::vector< NdrNodeConstPtr > NdrNodeConstPtrVec
Definition: declare.h:75
NdrRegistry & operator=(const NdrRegistry &)=delete
GLuint const GLchar * name
Definition: glcorearb.h:786
NDR_API NdrNodeConstPtr GetNodeByIdentifier(const NdrIdentifier &identifier, const NdrTokenVec &sourceTypePriority=NdrTokenVec())
friend class _DiscoveryContext
Definition: registry.h:284
NDR_API NdrRegistry()
Definition: hash.h:447
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
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
NDR_API NdrNodeConstPtr GetNodeFromSourceCode(const std::string &sourceCode, const TfToken &sourceType, const NdrTokenMap &metadata)
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glcorearb.h:1297
NdrDiscoveryPluginRefPtrVector DiscoveryPluginRefPtrVec
Definition: registry.h:67
#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:1394
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
GLenum GLint * range
Definition: glcorearb.h:1925
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)
NDR_API NdrTokenVec GetAllNodeSourceTypes() const