Belle II Software  release-08-01-10
RelationIndexContainer.h
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #pragma once
10 
11 #include <framework/datastore/StoreArray.h>
12 #include <framework/datastore/RelationArray.h>
13 
14 #include <boost/multi_index_container.hpp>
15 #include <boost/multi_index/ordered_index.hpp>
16 #include <boost/multi_index/member.hpp>
17 
18 namespace Belle2 {
32  public:
33 
35  virtual ~RelationIndexBase() {}
36 
38  virtual void clear() = 0;
39  };
40 
50  template<class FROM, class TO> class RelationIndexContainer: public RelationIndexBase {
51  public:
52 
54  struct Element {
55 
58  const FROM* from_, const TO* to_, RelationElement::weight_type weight_):
59  indexFrom(indexFrom_), indexTo(indexTo_), from(from_), to(to_), weight(weight_) {}
60 
63 
66 
68  const FROM* from;
69 
71  const TO* to;
72 
75  };
76 
81  typedef boost::multi_index::multi_index_container <
82  Element,
83  boost::multi_index::indexed_by <
84  boost::multi_index::ordered_non_unique <
85  boost::multi_index::member<Element, const FROM*, &Element::from>
86  >,
87  boost::multi_index::ordered_non_unique <
88  boost::multi_index::member<Element, const TO*, &Element::to>
89  >
90  >
92 
94  operator bool() const { return m_valid; }
95 
97  const ElementIndex& index() const { return m_index; }
99  ElementIndex& index() { return m_index; }
100 
103 
106 
108  const AccessorParams& getToAccessorParams() const { return m_storeTo; }
109 
110  protected:
115  explicit RelationIndexContainer(const RelationArray& relArray): m_storeRel(relArray), m_valid(false)
116  {
117  rebuild(true);
118  }
119 
122 
125 
131  void rebuild(bool force = false);
132 
134  virtual void clear() override { m_index.clear(); }
135 
138 
141 
144 
147 
149  bool m_valid;
150 
152  friend class RelationIndexManager;
153  };
154 
156  template<class FROM, class TO> void RelationIndexContainer<FROM, TO>::rebuild(bool force)
157  {
158  m_valid = m_storeRel.isValid();
159  if (!m_valid) {
160  B2DEBUG(100, "Relation " << m_storeRel.getName() << " does not exist, cannot build index");
161  m_index.clear();
162  m_storeFrom = AccessorParams();
163  m_storeTo = AccessorParams();
164  return;
165  }
166 
167  //Check if relation has been modified since we created the index
168  //If not, keep old contents
169  if (!force && !m_storeRel.getModified()) return;
170 
171  B2DEBUG(100, "Building index for " << m_storeRel.getName());
172 
173  //Reset modification flag
174  m_storeRel.setModified(false);
175 
176  m_index.clear();
177 
178  //Get related StoreArrays
179  m_storeFrom = m_storeRel.getFromAccessorParams();
180  m_storeTo = m_storeRel.getToAccessorParams();
181  const StoreArray<FROM> storeFrom(m_storeFrom.first, m_storeFrom.second);
182  const StoreArray<TO> storeTo(m_storeTo.first, m_storeTo.second);
183 
184  //Get number of entries in relation and stores (also checks template type versus DataStore contents)
185  const RelationElement::index_type nFrom = storeFrom.getEntries();
186  const RelationElement::index_type nTo = storeTo.getEntries();
187  const unsigned int nRel = m_storeRel.getEntries();
188 
189  //Loop over all RelationElements and add them to index
190  for (unsigned int i = 0; i < nRel; ++i) {
191  const RelationElement& r = m_storeRel[i];
192  RelationElement::index_type idxFrom = r.getFromIndex();
193  if (idxFrom >= nFrom)
194  B2FATAL("Relation " << m_storeRel.getName() << " is inconsistent: from-index (" << idxFrom << ") out of range");
195  const FROM* from = storeFrom[idxFrom];
196 
197  //Loop over index and weight vector at once
198  const auto& indices = r.getToIndices();
199  const auto& weights = r.getWeights();
200  auto itIdx = indices.begin();
201  auto itWgt = weights.begin();
202  const auto& idxEnd = indices.end();
203  for (; itIdx != idxEnd; ++itIdx, ++itWgt) {
204  const RelationElement::index_type idxTo = *itIdx;
205  if (idxTo >= nTo)
206  B2FATAL("Relation " << m_storeRel.getName() << " is inconsistent: to-index (" << idxTo << ") out of range");
207  const TO* to = storeTo[idxTo];
208  m_index.insert(Element(idxFrom, idxTo, from, to, *itWgt));
209  }
210  }
211  }
212 
214 } // end namespace Belle2
Low-level class to create/modify relations between StoreArrays.
Definition: RelationArray.h:62
Class to store a single element of a relation.
unsigned int index_type
type used for indices.
float weight_type
type used for weights.
Baseclass for all RelationIndexContainers.
virtual void clear()=0
Clear the index (at the end of the event)
virtual ~RelationIndexBase()
Virtual destructor to create vtable.
Class to store a bidirectional index between two StoreArrays.
RelationIndexContainer(const RelationIndexContainer &)=delete
Restrict copies.
RelationArray m_storeRel
the underlying relation.
RelationIndexContainer & operator=(const RelationIndexContainer &)=delete
Restrict copies.
AccessorParams m_storeFrom
AccessorParams of the StoreArray the relation points from.
RelationIndexContainer(const RelationArray &relArray)
Constructor to create a new IndexContainer.
const AccessorParams & getFromAccessorParams() const
Get the AccessorParams of the StoreArray the relation points from.
const AccessorParams & getToAccessorParams() const
Get the AccessorParams of the StoreArray the relation points to.
const ElementIndex & index() const
Get the index.
bool m_valid
Indicate wether the relation is valid.
virtual void clear() override
Clear the index (at the end of an event)
AccessorParams getAccessorParams() const
Get the AccessorParams of the underlying relation.
boost::multi_index::multi_index_container< Element, boost::multi_index::indexed_by< boost::multi_index::ordered_non_unique< boost::multi_index::member< Element, const FROM *, &Element::from > >, boost::multi_index::ordered_non_unique< boost::multi_index::member< Element, const TO *, &Element::to > > > > ElementIndex
Boost MultiIndex container to keep the bidirectional index.
ElementIndex m_index
Instance of the index.
AccessorParams m_storeTo
AccessorParams of the StoreArray the relation points to.
ElementIndex & index()
Get the index.
Manager to keep a cache of existing RelationIndexContainers.
AccessorParams getAccessorParams() const
Return pair of name and durability under which stored object is saved.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:216
void rebuild(bool force=false)
Rebuild the index.
std::pair< std::string, DataStore::EDurability > AccessorParams
Pair of parameters needed to find an object in the DataStore.
Abstract base class for different kinds of events.
const FROM * from
pointer of the element from which the relation points.
const TO * to
pointer of the element to which the relation points.
RelationElement::index_type indexTo
index of the element to which the relation points.
RelationElement::index_type indexFrom
index of the element from which the relation points.
RelationElement::weight_type weight
weight of the relation.
Element(RelationElement::index_type indexFrom_, RelationElement::index_type indexTo_, const FROM *from_, const TO *to_, RelationElement::weight_type weight_)
Create a new element.