ProductRegistry

Transients

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
#ifndef DataFormats_Provenance_ProductRegistry_h
#define DataFormats_Provenance_ProductRegistry_h

/** \class edm::ProductRegistry

     \original author Stefano ARGIRO
     \current author Bill Tanenbaum
     \date 19 Jul 2005
*/

#include "DataFormats/Provenance/interface/ProductDescription.h"
#include "DataFormats/Provenance/interface/BranchKey.h"
#include "DataFormats/Provenance/interface/BranchListIndex.h"
#include "DataFormats/Provenance/interface/BranchType.h"
#include "FWCore/Utilities/interface/ProductKindOfType.h"
#include "FWCore/Utilities/interface/ProductResolverIndex.h"
#include "FWCore/Utilities/interface/get_underlying_safe.h"

#include <array>
#include <memory>

#include <iosfwd>
#include <map>
#include <set>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>

namespace edm {
  class SignallingProductRegistryFiller;
  class ProductResolverIndexHelper;
  class TypeID;

  class ProductRegistry {
  public:
    friend class SignallingProductRegistryFiller;

    typedef std::map<BranchKey, ProductDescription> ProductList;

    ProductRegistry() = default;
    ProductRegistry(const ProductRegistry&) = default;
    ProductRegistry(ProductRegistry&&) = default;
    ProductRegistry& operator=(ProductRegistry&&) = default;
    // A constructor from the persistent data members from another product registry.
    // saves time by not copying the transient components.
    // The constructed registry will be frozen by default.
    explicit ProductRegistry(ProductList const& productList, bool toBeFrozen = true);

    ~ProductRegistry() = default;

    typedef std::map<BranchKey, ProductDescription const> ConstProductList;

    void copyProduct(ProductDescription const& productdesc);

    void setFrozen(bool initializeLookupInfo = true);

    void setFrozen(std::set<TypeID> const& productTypesConsumed,
                   std::set<TypeID> const& elementTypesConsumed,
                   std::string const& processName);

    void setUnscheduledProducts(std::set<std::string> const& unscheduledLabels);

    std::string merge(ProductRegistry const& other,
                      std::string const& fileName,
                      ProductDescription::MatchMode branchesMustMatch = ProductDescription::Permissive);

    void updateFromInput(ProductList const& other);

    void updateFromInput(std::vector<ProductDescription> const& other);

    ProductList const& productList() const {
      //throwIfNotFrozen();
      return productList_;
    }

    ProductList& productListUpdator() {
      throwIfFrozen();
      return productList_;
    }

    // Return all the branch names currently known to *this.  This
    // does a return-by-value of the vector so that it may be used in
    // a colon-initialization list.
    std::vector<std::string> allBranchNames() const;

    // Return pointers to (const) ProductDescriptions for all the
    // ProductDescriptions known to *this.  This does a
    // return-by-value of the vector so that it may be used in a
    // colon-initialization list.
    std::vector<ProductDescription const*> allProductDescriptions() const;

    ProductList::size_type size() const { return productList_.size(); }

    //If the value differs between two versions of the main registry then
    // one must update any related meta data
    using CacheID = ProductList::size_type;
    CacheID cacheIdentifier() const { return size(); }

    void print(std::ostream& os) const;

    bool anyProducts(BranchType const brType) const;

    std::shared_ptr<ProductResolverIndexHelper const> productLookup(BranchType branchType) const;

    // returns the appropriate ProductResolverIndex else ProductResolverIndexInvalid if no BranchID is available
    ProductResolverIndex indexFrom(BranchID const& iID) const;

    bool productProduced(BranchType branchType) const { return transient_.productProduced_[branchType]; }
    bool anyProductProduced() const { return transient_.anyProductProduced_; }

    // Looks if a (type, moduleLabel, productInstanceName) is an alias to some other branch
    //
    // Can return multiple modules if kindOfType is ELEMENT_TYPE (i.e.
    // the product is consumed via edm::View) and there is ambiguity
    // (in which case actual Event::get() would eventually lead to an
    // exception). In that case all possible modules whose product
    // could be consumed are returned.
    std::vector<std::string> aliasToModules(KindOfType kindOfType,
                                            TypeID const& type,
                                            std::string_view moduleLabel,
                                            std::string_view productInstanceName) const;

    ProductResolverIndex const& getNextIndexValue(BranchType branchType) const;

    void initializeTransients() { transient_.reset(); }

    bool frozen() const { return transient_.frozen_; }

    struct Transients {
      Transients();
      void reset();

      bool frozen_;
      // Is at least one (run), (lumi), (event) persistent product produced this process?
      std::array<bool, NumBranchTypes> productProduced_;
      bool anyProductProduced_;

      std::array<std::shared_ptr<const ProductResolverIndexHelper>, NumBranchTypes> productLookups_;

      std::array<ProductResolverIndex, NumBranchTypes> nextIndexValues_;

      std::map<BranchID, ProductResolverIndex> branchIDToIndex_;

      enum { kKind, kType, kModuleLabel, kProductInstanceName, kAliasForModuleLabel };
      using AliasToOriginalVector = std::vector<std::tuple<KindOfType, TypeID, std::string, std::string, std::string>>;
      AliasToOriginalVector aliasToOriginal_;
    };

  private:
    //The following three routines are only called by SignallingProductRegistryFiller
    void addProduct_(ProductDescription const& productdesc);

    ProductDescription const& addLabelAlias_(ProductDescription const& productdesc,
                                             std::string const& labelAlias,
                                             std::string const& instanceAlias);

    // triggers callbacks for modules watching registration
    template <typename F>
    void addFromInput_(edm::ProductRegistry const& iReg, F&& iCallback) {
      throwIfFrozen();
      for (auto const& prod : iReg.productList_) {
        ProductList::iterator iter = productList_.find(prod.first);
        if (iter == productList_.end()) {
          productList_.insert(std::make_pair(prod.first, prod.second));
          iCallback(prod.second);
        } else {
          assert(combinable(iter->second, prod.second));
          iter->second.merge(prod.second);
        }
      }
    }

  private:
    void setProductProduced(BranchType branchType) {
      transient_.productProduced_[branchType] = true;
      transient_.anyProductProduced_ = true;
    }

    void freezeIt(bool frozen = true) { transient_.frozen_ = frozen; }

    void initializeLookupTables(std::set<TypeID> const* productTypesConsumed,
                                std::set<TypeID> const* elementTypesConsumed,
                                std::string const* processName);
    void addElementTypesForAliases(std::set<TypeID> const* elementTypesConsumed,
                                   std::map<TypeID, TypeID> const& containedTypeMap,
                                   std::map<TypeID, std::vector<TypeID>> const& containedTypeToBaseTypesMap);

    void checkDictionariesOfConsumedTypes(std::set<TypeID> const* productTypesConsumed,
                                          std::set<TypeID> const* elementTypesConsumed,
                                          std::map<TypeID, TypeID> const& containedTypeMap,
                                          std::map<TypeID, std::vector<TypeID>>& containedTypeToBaseTypesMap);

    void checkForDuplicateProcessName(ProductDescription const& desc, std::string const* processName) const;

    void throwIfNotFrozen() const;
    void throwIfFrozen() const;

    ProductResolverIndex& nextIndexValue(BranchType branchType);

    ProductList productList_;
    Transients transient_;
  };

  inline bool operator==(ProductRegistry const& a, ProductRegistry const& b) {
    return a.productList() == b.productList();
  }

  inline bool operator!=(ProductRegistry const& a, ProductRegistry const& b) { return !(a == b); }

  inline std::ostream& operator<<(std::ostream& os, ProductRegistry const& pr) {
    pr.print(os);
    return os;
  }

}  // namespace edm

#endif