Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-04-08 00:35:05

0001 #ifndef DataFormats_Provenance_ProductResolverIndexHelper_h
0002 #define DataFormats_Provenance_ProductResolverIndexHelper_h
0003 
0004 /** \class edm::ProductResolverIndexHelper
0005 
0006 This class assigns and gets the ProductResolverIndex
0007 associated with a type, module label, instance, and
0008 process.  The ProductResolverIndex is used to tell the
0009 Principal where to store a ProductResolver and how to find
0010 it quickly.
0011 
0012 One can also look up the same ProductResolverIndex's using
0013 the type or base type of an element in a container in the
0014 product (if the product is a container). In this case the
0015 KindOfType argument to the Principal::getByLabel function
0016 is ELEMENT_TYPE, whereas normally it is PRODUCT_TYPE.
0017 
0018 There are also special ProductResolverIndex's generated
0019 where the process name is empty. These indexes refer
0020 to a special ProductResolvers that search for a matching
0021 product from the most recent process that has a matching
0022 type, label and instance. There is ProductResolverIndex
0023 generated for each type/label/instance combination which
0024 has at least one entry in the tables in this class.
0025 Both PRODUCT_TYPEs and ELEMENT_TYPEs get these special
0026 ProductResolvers.
0027 
0028 The ProductResolverIndex for a particular product
0029 will not change during a process after the ProductRegistry
0030 has been frozen. Nor will any of the other member data
0031 of this class. Multiple threads can access it concurrently
0032 without problems. The ProductResolverIndexes can be safely
0033 cached in InputTags and possibly other places, because
0034 they never change within a process. The ProductResolverIndex
0035 for a particular product is not intended to be persistent
0036 and will be different in different processes.
0037 
0038 The ProductResolverIndex is used to order the placement of
0039 the ProductResolvers in the Principal that are either
0040 present in the input or produced in the current process.
0041 Be aware that there are other ProductResolvers for products
0042 that come after ProductResolvers placed by this class.
0043 For example, the placement of dropped products
0044 is not handled by this class, instead by the ProductRegistry.
0045 The reason for this distinction is that those other
0046 ProductResolvers can change and be added as a process runs.
0047 The content of this class never changes after the
0048 ProductRegistry is frozen.
0049 
0050 \author W. David Dagenhart, created 10 December, 2012 
0051 
0052 */
0053 
0054 #include "FWCore/Utilities/interface/ProductResolverIndex.h"
0055 #include "FWCore/Utilities/interface/ProductKindOfType.h"
0056 #include "FWCore/Utilities/interface/TypeID.h"
0057 #include "FWCore/Utilities/interface/propagate_const.h"
0058 
0059 #include <iosfwd>
0060 #include <memory>
0061 #include <set>
0062 #include <string>
0063 #include <vector>
0064 #include <tuple>
0065 #include <unordered_map>
0066 
0067 namespace edm {
0068 
0069   class TypeWithDict;
0070 
0071   namespace productholderindexhelper {
0072     // The next function supports views. For the given wrapped type,
0073     // which must be Wrapper<T>,
0074     // this function returns the type of the contained type of T.
0075     // If the type is not a recongnized container, it returns
0076     // a TypeID(typeid(void)).
0077     TypeID getContainedTypeFromWrapper(TypeID const& wrappedtypeID, std::string const& className);
0078 
0079     // The next function supports views. For the given type T,
0080     // this function returns the type of the contained type of T.
0081     // If the type is not a recongnized container, it returns
0082     // a TypeID(typeid(void)).
0083     // This calls getContainedTypefromWrapped internally
0084     // If the TypeID for the wrapped type is already available,
0085     // it is faster to call getContainedTypeFromWrapper directly.
0086     TypeID getContainedType(TypeID const& typeID);
0087 
0088     bool typeIsViewCompatible(TypeID const& requestedViewType,
0089                               TypeID const& wrappedtypeID,
0090                               std::string const& className);
0091   }  // namespace productholderindexhelper
0092 
0093   class ProductResolverIndexHelper {
0094   public:
0095     ProductResolverIndexHelper();
0096 
0097     // The accessors below return a ProductResolverIndex that matches
0098     // the arguments or a set of matching indexes using the Matches
0099     // class. A returned index can have a value that indicates that it
0100     // is invalid or ambiguous and the client should check for these
0101     // values before using the index (see ProductResolverIndex.h).
0102 
0103     // If no matches are found or the ProductResolverIndexHelper
0104     // has not been frozen yet, then an invalid index or a Matches
0105     // object with numberOfMatches equal to 0 will be returned.
0106 
0107     // The ambiguous values can occur when the kind of type is ELEMENT_TYPE
0108     // type. ELEMENT_TYPE is the type or base type of an object
0109     // stored in a container that is the product. These types are used
0110     // with data requests that use Views. For PRODUCT_TYPE types, ambiguity
0111     // is not possible.
0112 
0113     // The next function returns the index for the one group that
0114     // matches the type, module label, instance, and process.
0115     // The 3 pointer arguments must point to C style strings terminated
0116     // by a '\0' with the one following possible exception. If the
0117     // process pointer is null or the process string empty, then
0118     // this returns the index of the special ProductResolver that
0119     // knows how to search for the product matching the type, module
0120     // label, and instance and which is from the most recent process.
0121     ProductResolverIndex index(KindOfType kindOfType,
0122                                TypeID const& typeID,
0123                                char const* moduleLabel,
0124                                char const* instance,
0125                                char const* process = nullptr) const;
0126 
0127     using ModulesToIndiciesMap =
0128         std::unordered_multimap<std::string, std::tuple<TypeID const*, const char*, ProductResolverIndex>>;
0129     ModulesToIndiciesMap indiciesForModulesInProcess(const std::string& iProcessName) const;
0130 
0131     class Matches {
0132     public:
0133       Matches(ProductResolverIndexHelper const* productResolverIndexHelper,
0134               unsigned int startInIndexAndNames,
0135               unsigned int numberOfMatches);
0136 
0137       ProductResolverIndex index(unsigned int i) const;
0138       unsigned int numberOfMatches() const { return numberOfMatches_; }
0139       bool isFullyResolved(unsigned int i) const;
0140       char const* moduleLabel(unsigned int i) const;
0141       char const* productInstanceName(unsigned int i) const;
0142       char const* processName(unsigned int i) const;
0143 
0144     private:
0145       ProductResolverIndexHelper const* productResolverIndexHelper_;
0146       unsigned int startInIndexAndNames_;
0147       unsigned int numberOfMatches_;
0148     };
0149 
0150     // Return ProductResolverIndex's for all product holders that
0151     // match the type, module label, and product instance name.
0152     // The pointer arguments must be C style strings terminated
0153     // by a '\0'.
0154     Matches relatedIndexes(KindOfType kindOfType,
0155                            TypeID const& typeID,
0156                            char const* moduleLabel,
0157                            char const* instance) const;
0158 
0159     // Return indexes for all groups that match the type.
0160     Matches relatedIndexes(KindOfType kindOfType, TypeID const& typeID) const;
0161 
0162     // This will throw if called after the object is frozen.
0163     // The typeID must be for a type with a dictionary
0164     // (the calling function is expected to check that)
0165     // The pointer arguments must point at C style strings
0166     // terminated by '\0'.
0167     // 1. This creates an entry and new ProductResolverIndex for
0168     // the product if it does not already exist. If it
0169     // does exist then it throws.
0170     // 2. If it does not already exist, this will create an
0171     // entry and new ProductResolverIndex for the ProductResolver
0172     // that will search for the matching type, label, and
0173     // instance for the most recent process (internally indicated
0174     // by an empty process string).
0175     // This will then loop over the contained class (if it exists)
0176     // and the base classes of the contained class.
0177     // 1. If the matching type, label, instance, and process
0178     // already exist then that entry is modified and marked
0179     // ambiguous. If not, it inserts an entry which uses the same
0180     // ProductResolverIndex as the containing product.
0181     // 2. If it does not already exist it inserts a new
0182     // entry with a new ProductResolverIndex for the case
0183     // which searches for the most recent process.
0184     ProductResolverIndex insert(TypeID const& typeID,
0185                                 char const* moduleLabel,
0186                                 char const* instance,
0187                                 char const* process,
0188                                 TypeID const& containedTypeID,
0189                                 std::vector<TypeWithDict>* baseTypesOfContainedType);
0190 
0191     ProductResolverIndex insert(TypeID const& typeID,
0192                                 char const* moduleLabel,
0193                                 char const* instance,
0194                                 char const* process);
0195 
0196     // Before the object is frozen the accessors above will
0197     // fail to find a match. Once frozen, no more new entries
0198     // can be added with insert.
0199     void setFrozen();
0200 
0201     std::vector<std::string> const& lookupProcessNames() const;
0202 
0203     class Range {
0204     public:
0205       Range(unsigned int begin, unsigned int end) : begin_(begin), end_(end) {}
0206       unsigned int begin() const { return begin_; }
0207       unsigned int end() const { return end_; }
0208 
0209     private:
0210       unsigned int begin_;
0211       unsigned int end_;
0212     };
0213 
0214     class IndexAndNames {
0215     public:
0216       IndexAndNames(ProductResolverIndex index, unsigned int start, unsigned int startProcess)
0217           : index_(index), startInBigNamesContainer_(start), startInProcessNames_(startProcess) {}
0218       ProductResolverIndex index() const { return index_; }
0219       unsigned int startInBigNamesContainer() const { return startInBigNamesContainer_; }
0220       unsigned int startInProcessNames() const { return startInProcessNames_; }
0221 
0222     private:
0223       ProductResolverIndex index_;
0224       unsigned int startInBigNamesContainer_;
0225       unsigned int startInProcessNames_;
0226     };
0227 
0228     unsigned int beginElements() const { return beginElements_; }
0229     std::vector<TypeID> const& sortedTypeIDs() const { return sortedTypeIDs_; }
0230     std::vector<Range> const& ranges() const { return ranges_; }
0231     std::vector<IndexAndNames> const& indexAndNames() const { return indexAndNames_; }
0232     std::vector<char> const& processNames() const { return processNames_; }
0233 
0234     // The next few functions are intended for internal use
0235     // but are public so tests can use them also.
0236 
0237     unsigned int indexToIndexAndNames(KindOfType kindOfType,
0238                                       TypeID const& typeID,
0239                                       char const* moduleLabel,
0240                                       char const* instance,
0241                                       char const* process) const;
0242 
0243     // Returns the index into sortedTypeIDs_. Returns the maximum unsigned
0244     // int value if the type is not there.
0245     unsigned int indexToType(KindOfType kindOfType, TypeID const& typeID) const;
0246 
0247     // Returns the index of the process name in processNames_. Returns the
0248     // maximum unsigned int value if the process name is not found.
0249     unsigned int processIndex(char const* process) const;
0250 
0251     // This will throw if it detects problems, but unless there is a bug
0252     // there should never be any. Mostly it is checking for things which
0253     // might cause out of bounds errors when accessing the vectors.
0254     void sanityCheck() const;
0255 
0256     ProductResolverIndex nextIndexValue() const { return nextIndexValue_; }
0257 
0258     // For debugging only
0259     void print(std::ostream& os) const;
0260 
0261   private:
0262     // Next available value for a ProductResolverIndex. This just
0263     // increments by one each time a new value is assigned.
0264     ProductResolverIndex nextIndexValue_;
0265 
0266     // This is an index into sortedTypeIDs_ that tells where
0267     // the entries corresponding to types of elements in containers
0268     // start.
0269     unsigned int beginElements_;
0270 
0271     // Sorted by putting all the product entries first and
0272     // then the element entries.  Then sorted by TypeID value.
0273     // Most lookups start here by finding the TypeID and
0274     // then using its position to find the corresponding Range
0275     // in the ranges_ vector below.
0276     std::vector<TypeID> sortedTypeIDs_;
0277 
0278     // There is a one to one correspondence between this vector
0279     // and sortedTypeIDs_ and the corresponding elements appear
0280     // in the same order. Each Range object holds the beginning and
0281     // end of the corresponding elements in the indexAndNames_
0282     // vector below.
0283     std::vector<Range> ranges_;
0284 
0285     // Each element of this vector contains a ProductResolverIndex.
0286     // It also contains indexes into vectors of characters that
0287     // hold the corresponding moduleLabel, instance, and process
0288     // name. Note this is sorted with product entries first then
0289     // element entries, then by TypeID, then by moduleLabel,
0290     // then by instance, and finally by process. Note that in
0291     // a subset of entries that have matching type/label/instance
0292     // the entry with an empty process name will always be the
0293     // first process and startInProcessNames_ will always be 0
0294     // for the empty process name.
0295     std::vector<IndexAndNames> indexAndNames_;
0296 
0297     // These contain C style strings terminated
0298     // by '\0' all concatenated together. In the
0299     // first vector the strings come in pairs,
0300     // always module label then instance.  The pairs
0301     // are ordered the same as the IndexAndNames
0302     // vector. Within a TypeID, the moduleLabel/instance
0303     // pair is not duplicated if it appears multiple times.
0304     // The second vector contains all the process names
0305     // in alphabetical order with no duplication. The
0306     // first element is always the empty string.
0307     std::vector<char> bigNamesContainer_;
0308     std::vector<char> processNames_;
0309 
0310     // Duplicates the entries in processNames_ in
0311     // a convenient format.
0312     std::vector<std::string> lookupProcessNames_;
0313 
0314     // The rest of the data members are for temporary use
0315     // while the data structure is being filled.
0316 
0317     class Item {
0318     public:
0319       Item(KindOfType kindOfType,
0320            TypeID const& typeID,
0321            std::string const& moduleLabel,
0322            std::string const& instance,
0323            std::string const& process,
0324            ProductResolverIndex index);
0325       KindOfType kindOfType() const { return kindOfType_; }
0326       TypeID const& typeID() const { return typeID_; }
0327       std::string const& moduleLabel() const { return moduleLabel_; }
0328       std::string const& instance() const { return instance_; }
0329       std::string const& process() const { return process_; }
0330       ProductResolverIndex index() const { return index_; }
0331 
0332       void clearProcess() { process_.clear(); }
0333       void setIndex(ProductResolverIndex v) { index_ = v; }
0334 
0335       bool operator<(Item const& right) const;
0336 
0337     private:
0338       KindOfType kindOfType_;
0339       TypeID typeID_;
0340       std::string moduleLabel_;
0341       std::string instance_;
0342       std::string process_;
0343       ProductResolverIndex index_;
0344     };
0345 
0346     edm::propagate_const<std::unique_ptr<std::set<Item>>> items_;
0347 
0348     edm::propagate_const<std::unique_ptr<std::set<std::string>>> processItems_;
0349   };
0350 }  // namespace edm
0351 #endif