The Gaudi Framework  v36r1 (3e2fb5a8)
EvtStoreSvc.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 #include "Gaudi/Accumulators.h"
12 #include "Gaudi/Arena/Monotonic.h"
19 #include "GaudiKernel/IRegistry.h"
20 #include "GaudiKernel/Service.h"
21 #include "GaudiKernel/System.h"
22 #include "tbb/concurrent_queue.h"
23 
24 #include "ThreadLocalStorage.h"
25 
26 #include "boost/algorithm/string/predicate.hpp"
27 
28 #include <algorithm>
29 #include <iomanip>
30 #include <iterator>
31 #include <map>
32 #include <mutex>
33 #include <stdexcept>
34 #include <type_traits>
35 #include <unordered_map>
36 #include <utility>
37 #include <vector>
38 
39 namespace {
40  using LocalArena = Gaudi::Arena::Monotonic<>;
41 
42  template <typename T>
43  using LocalAlloc = Gaudi::Allocator::MonotonicArena<T>;
44 
45  using pool_string = std::basic_string<char, std::char_traits<char>, LocalAlloc<char>>;
46 
47  class Entry final : public IRegistry {
50  pool_string m_identifierStorage;
51  mutable std::optional<std::string> m_identifier;
52  static IDataProviderSvc* s_svc;
53 
54  public:
55  using allocator_type = LocalAlloc<char>;
56  static void setDataProviderSvc( IDataProviderSvc* p ) { s_svc = p; }
57 
58  Entry( std::string_view id, std::unique_ptr<DataObject> data, std::unique_ptr<IOpaqueAddress> addr,
59  allocator_type alloc ) noexcept
60  : m_data{std::move( data )}, m_addr{std::move( addr )}, m_identifierStorage{id, alloc} {
61  if ( m_data ) m_data->setRegistry( this );
62  if ( m_addr ) m_addr->setRegistry( this );
63  }
64  Entry( const Entry& ) = delete;
65  Entry& operator=( const Entry& rhs ) = delete;
66  Entry( Entry&& rhs ) = delete;
67  Entry& operator=( Entry&& rhs ) = delete;
68 
69  // required by IRegistry...
70  unsigned long addRef() override { return -1; }
71  unsigned long release() override { return -1; }
72  const name_type& name() const override {
73  // should really be from last '/' onward...
74  if ( !m_identifier ) m_identifier.emplace( m_identifierStorage );
75  return *m_identifier;
76  }
77  const id_type& identifier() const override {
78  if ( !m_identifier ) m_identifier.emplace( m_identifierStorage );
79  return *m_identifier;
80  }
81  std::string_view identifierView() const { return m_identifierStorage; }
82  IDataProviderSvc* dataSvc() const override { return s_svc; }
83  DataObject* object() const override { return const_cast<DataObject*>( m_data.get() ); }
84  IOpaqueAddress* address() const override { return m_addr.get(); }
85  void setAddress( IOpaqueAddress* iAddr ) override {
86  m_addr.reset( iAddr );
87  if ( m_addr ) m_addr->setRegistry( this );
88  }
89  };
90  IDataProviderSvc* Entry::s_svc = nullptr;
91 
92  using UnorderedMap =
94  LocalAlloc<std::pair<const std::string_view, Entry>>>;
95  using OrderedMap = std::map<std::string_view, Entry>;
96 
97  template <typename Map = UnorderedMap>
98  class Store {
99  LocalArena m_resource;
100  std::size_t m_est_size;
101  // Optional purely to make [re]construction simpler, should "always" be valid
102  std::optional<Map> m_store{std::in_place, &m_resource};
103  static_assert( std::is_same_v<typename Map::key_type, std::string_view> );
104 
105  const auto& emplace( std::string_view k, std::unique_ptr<DataObject> d, std::unique_ptr<IOpaqueAddress> a = {} ) {
106  // tricky way to insert a string_view key which points to the
107  // string contained in the mapped type...
108  auto [i, b] = m_store->try_emplace( k, k, std::move( d ), std::move( a ), &m_resource );
109  if ( !b ) throw std::runtime_error( "failed to insert " + std::string{k} );
110  auto nh = m_store->extract( i );
111  nh.key() = nh.mapped().identifierView(); // "re-point" key to the string contained in the Entry
112  auto r = m_store->insert( std::move( nh ) );
113  if ( !r.inserted ) throw std::runtime_error( "failed to insert " + std::string{k} );
114  return r.position->second;
115  }
116 
117  public:
118  Store( std::size_t est_size, std::size_t pool_size ) : m_resource{pool_size}, m_est_size{est_size} {}
119  [[nodiscard]] bool empty() const { return m_store->empty(); }
120  [[nodiscard]] std::size_t size() const { return m_store->size(); }
121  [[nodiscard]] std::size_t used_bytes() const noexcept { return m_resource.size(); }
122  [[nodiscard]] std::size_t used_blocks() const noexcept { return m_resource.num_blocks(); }
123  [[nodiscard]] std::size_t used_buckets() const { return m_store->bucket_count(); }
124  [[nodiscard]] std::size_t num_allocations() const noexcept { return m_resource.num_allocations(); }
125 
126  void reset() {
127  m_store.reset(); // kill the old map
128  m_resource.reset(); // tell the memory pool it can start re-using its resources
129  m_store.emplace( m_est_size, &m_resource ); // initialise the new map with a sane number of buckets
130  }
131 
132  const DataObject* put( std::string_view k, std::unique_ptr<DataObject> data,
133  std::unique_ptr<IOpaqueAddress> addr = {} ) {
134  return emplace( k, std::move( data ), std::move( addr ) ).object();
135  }
136  const DataObject* get( std::string_view k ) const noexcept {
137  const Entry* d = find( k );
138  return d ? d->object() : nullptr;
139  }
140  const Entry* find( std::string_view k ) const noexcept {
141  auto i = m_store->find( k );
142  return i != m_store->end() ? &( i->second ) : nullptr;
143  }
144 
145  [[nodiscard]] auto begin() const noexcept { return m_store->begin(); }
146  [[nodiscard]] auto end() const noexcept { return m_store->end(); }
147  void clear() noexcept { m_store->clear(); }
148  auto erase( std::string_view k ) { return m_store->erase( k ); }
149  template <typename Predicate>
150  void erase_if( Predicate p ) {
151  auto i = m_store->begin();
152  auto end = m_store->end();
153  while ( i != end ) {
154  if ( std::invoke( p, std::as_const( *i ) ) )
155  i = m_store->erase( i );
156  else
157  ++i;
158  }
159  }
160  };
161 
162  StatusCode dummy( std::string s ) {
163  std::string trace;
164  System::backTrace( trace, 6, 2 );
165  throw std::logic_error{"Unsupported Function Called: " + s + "\n" + trace};
166  return StatusCode::FAILURE;
167  }
168 
169  std::string_view normalize_path( std::string_view path, std::string_view prefix ) {
170  if ( path.size() >= prefix.size() && std::equal( prefix.begin(), prefix.end(), path.begin() ) )
171  path.remove_prefix( prefix.size() );
172  if ( !path.empty() && path.front() == '/' ) path.remove_prefix( 1 );
173  return path;
174  }
175 
177  DataObject* pObject = nullptr;
178  auto status = cnv.createObj( &addr, pObject ); // Call data loader
179  auto object = std::unique_ptr<DataObject>( pObject );
180  if ( status.isFailure() ) object.reset();
181  return object;
182  }
183 
184  // HiveWhiteBoard helpers
185  struct Partition final {
186  // Use optional to allow re-constructing in-place without an ugly
187  // exception-unsafe placement-new conconction, and also to make it easier
188  // to pass constructor arguments to Store<>.
189  std::optional<Store<>> store;
190  int eventNumber = -1;
191  };
192 
193  template <typename T, typename Mutex = std::recursive_mutex, typename ReadLock = std::scoped_lock<Mutex>,
194  typename WriteLock = ReadLock>
195  class Synced {
196  T m_obj;
197  mutable Mutex m_mtx;
198 
199  public:
200  template <typename F>
201  decltype( auto ) with_lock( F&& f ) {
202  WriteLock lock{m_mtx};
203  return f( m_obj );
204  }
205  template <typename F>
206  decltype( auto ) with_lock( F&& f ) const {
207  ReadLock lock{m_mtx};
208  return f( m_obj );
209  }
210  };
211  // transform an f(T) into an f(Synced<T>)
212  template <typename Fun>
213  auto with_lock( Fun&& f ) {
214  return [f = std::forward<Fun>( f )]( auto& p ) -> decltype( auto ) { return p.with_lock( f ); };
215  }
216 
217  TTHREAD_TLS( Synced<Partition>* ) s_current = nullptr;
218 
219  template <typename Fun>
220  StatusCode fwd( Fun&& f ) {
221  return s_current ? s_current->with_lock( std::forward<Fun>( f ) )
223  }
224 
225 } // namespace
226 
237 class GAUDI_API EvtStoreSvc : public extends<Service, IDataProviderSvc, IDataManagerSvc, IHiveWhiteBoard> {
238  Gaudi::Property<CLID> m_rootCLID{this, "RootCLID", 110 /*CLID_Event*/, "CLID of root entry"};
239  Gaudi::Property<std::string> m_rootName{this, "RootName", "/Event", "name of root entry"};
240  Gaudi::Property<bool> m_forceLeaves{this, "ForceLeaves", false, "force creation of default leaves on registerObject"};
241  Gaudi::Property<std::string> m_loader{this, "DataLoader", "EventPersistencySvc"};
242  Gaudi::Property<size_t> m_slots{this, "EventSlots", 1, "number of event slots"};
243  Gaudi::Property<bool> m_printPoolStats{this, "PrintPoolStats", false, "Print memory pool statistics"};
244  Gaudi::Property<std::size_t> m_poolSize{this, "PoolSize", 1024, "Initial per-event memory pool size [KiB]"};
245  Gaudi::Property<std::size_t> m_estStoreBuckets{this, "StoreBuckets", 100, "Estimated number of buckets in the store"};
247  m_usedPoolAllocations, m_storeEntries, m_storeBuckets;
248 
249  // Convert to bytes
250  std::size_t poolSize() const { return m_poolSize * 1024; }
251 
252  void fillStats( Partition& p ) const {
253  if ( LIKELY( !m_printPoolStats ) ) return;
254  auto n_allocs = p.store->num_allocations();
255  if ( n_allocs ) {
256  m_storeEntries += p.store->size();
257  m_usedPoolSize += p.store->used_bytes();
258  m_storeBuckets += p.store->used_buckets();
259  m_usedPoolAllocations += p.store->used_blocks();
260  m_servedPoolAllocations += n_allocs;
261  }
262  }
263 
264  void initStore( Partition& p ) const {
265  if ( p.store ) {
266  // re-use the existing memory pool
267  p.store->reset();
268  } else {
269  p.store.emplace( m_estStoreBuckets, poolSize() );
270  }
271  }
272 
274 
277 
280 
281  tbb::concurrent_queue<size_t> m_freeSlots;
282 
284  this,
285  "InhibitedPathPrefixes",
286  {},
287  "Prefixes of TES locations that will not be loaded by the persistency service "};
288  Gaudi::Property<bool> m_followLinksToAncestors{
289  this, "FollowLinksToAncestors", true,
290  "Load objects which reside in files other than the one corresponding to the root of the event store"};
291  std::string_view m_onlyThisID; // let's be a bit risky... we 'know' when the underlying string goes out of scope...
292 
293 public:
294  using extends::extends;
295 
296  CLID rootCLID() const override;
297  const std::string& rootName() const override;
298  StatusCode setDataLoader( IConversionSvc* svc, IDataProviderSvc* dpsvc ) override;
299 
300  size_t allocateStore( int evtnumber ) override;
301  StatusCode freeStore( size_t partition ) override;
302  size_t freeSlots() override { return m_freeSlots.unsafe_size(); }
303  StatusCode selectStore( size_t partition ) override;
304  StatusCode clearStore() override;
305  StatusCode clearStore( size_t partition ) override;
306  StatusCode setNumberOfStores( size_t slots ) override;
307  size_t getNumberOfStores() const override { return m_slots; }
308  size_t getPartitionNumber( int eventnumber ) const override;
309  bool exists( const DataObjID& id ) override {
310  DataObject* pObject{nullptr};
311  return findObject( id.fullKey(), pObject ).isSuccess();
312  }
313 
314  StatusCode objectParent( const DataObject*, IRegistry*& ) override { return dummy( __FUNCTION__ ); }
315  StatusCode objectParent( const IRegistry*, IRegistry*& ) override { return dummy( __FUNCTION__ ); }
316  StatusCode objectLeaves( const DataObject*, std::vector<IRegistry*>& ) override { return dummy( __FUNCTION__ ); }
317  StatusCode objectLeaves( const IRegistry*, std::vector<IRegistry*>& ) override { return dummy( __FUNCTION__ ); }
318 
319  StatusCode clearSubTree( std::string_view ) override;
320  StatusCode clearSubTree( DataObject* obj ) override {
321  return obj && obj->registry() ? clearSubTree( obj->registry()->identifier() ) : StatusCode::FAILURE;
322  }
323 
324  StatusCode traverseSubTree( std::string_view, IDataStoreAgent* ) override;
326  return ( obj && obj->registry() ) ? traverseSubTree( obj->registry()->identifier(), pAgent ) : StatusCode::FAILURE;
327  }
328  StatusCode traverseTree( IDataStoreAgent* pAgent ) override { return traverseSubTree( std::string_view{}, pAgent ); }
329 
330  StatusCode setRoot( std::string root_name, DataObject* pObject ) override;
331  StatusCode setRoot( std::string root_path, IOpaqueAddress* pRootAddr ) override;
332 
333  StatusCode unregisterAddress( std::string_view ) override { return dummy( __FUNCTION__ ); };
334  StatusCode unregisterAddress( IRegistry*, std::string_view ) override { return dummy( __FUNCTION__ ); };
335 
336  StatusCode registerAddress( std::string_view fullPath, IOpaqueAddress* pAddress ) override;
337  StatusCode registerAddress( IRegistry* parentObj, std::string_view objectPath, IOpaqueAddress* pAddress ) override;
338  StatusCode registerObject( std::string_view parentPath, std::string_view objectPath, DataObject* pObject ) override;
339  StatusCode registerObject( DataObject* parentObj, std::string_view objectPath, DataObject* pObject ) override;
340 
341  StatusCode unregisterObject( std::string_view ) override;
343  return ( obj && obj->registry() ) ? unregisterObject( obj->registry()->identifier() ) : StatusCode::FAILURE;
344  }
345  StatusCode unregisterObject( DataObject* obj, std::string_view sr ) override {
346  return !obj ? unregisterObject( sr )
347  : obj->registry() ? unregisterObject( ( obj->registry()->identifier() + '/' ).append( sr ) )
349  };
350 
351  StatusCode retrieveObject( IRegistry* pDirectory, std::string_view path, DataObject*& pObject ) override;
352 
353  StatusCode findObject( IRegistry* pDirectory, std::string_view path, DataObject*& pObject ) override;
354  StatusCode findObject( std::string_view fullPath, DataObject*& pObject ) override;
355 
356  StatusCode updateObject( IRegistry* ) override { return dummy( __FUNCTION__ ); }
357  StatusCode updateObject( DataObject* ) override { return dummy( __FUNCTION__ ); }
358 
359  StatusCode addPreLoadItem( const DataStoreItem& ) override;
360  StatusCode removePreLoadItem( const DataStoreItem& ) override;
362  m_preLoads.clear();
363  return StatusCode::SUCCESS;
364  }
365  StatusCode preLoad() override;
366 
367  StatusCode linkObject( IRegistry*, std::string_view, DataObject* ) override { return dummy( __FUNCTION__ ); }
368  StatusCode linkObject( std::string_view, DataObject* ) override { return dummy( __FUNCTION__ ); }
369  StatusCode unlinkObject( IRegistry*, std::string_view ) override { return dummy( __FUNCTION__ ); }
370  StatusCode unlinkObject( DataObject*, std::string_view ) override { return dummy( __FUNCTION__ ); }
371  StatusCode unlinkObject( std::string_view ) override { return dummy( __FUNCTION__ ); }
372 
373  StatusCode initialize() override {
374  Entry::setDataProviderSvc( this );
375  extends::initialize().ignore();
376  if ( !setNumberOfStores( m_slots ).isSuccess() ) {
377  error() << "Cannot set number of slots" << endmsg;
378  return StatusCode::FAILURE;
379  }
380  m_partitions = std::vector<Synced<Partition>>( m_slots );
381  // m_partitions is now full of empty std::optionals, fill them now.
382  for ( auto& synced_p : m_partitions ) {
383  synced_p.with_lock( [this]( Partition& p ) { initStore( p ); } );
384  }
385  for ( size_t i = 0; i < m_slots; i++ ) { m_freeSlots.push( i ); }
386  selectStore( 0 ).ignore();
387 
388  auto loader = serviceLocator()->service( m_loader ).as<IConversionSvc>().get();
389  if ( !loader ) {
390  error() << "Cannot get IConversionSvc " << m_loader.value() << endmsg;
391  return StatusCode::FAILURE;
392  }
393  return setDataLoader( loader, nullptr );
394  }
395  StatusCode finalize() override {
396  if ( m_printPoolStats ) {
397  info() << "Mean memory pool usage: " << float( 1e-3f * m_usedPoolSize.mean() ) << " KiB serving "
398  << float( m_servedPoolAllocations.mean() ) << " allocations from " << float( m_usedPoolAllocations.mean() )
399  << " to produce " << float( m_storeEntries.mean() ) << " entries in " << float( m_storeBuckets.mean() )
400  << " buckets" << endmsg;
401  }
402  setDataLoader( nullptr, nullptr ).ignore(); // release
403  return extends::finalize();
404  }
405 };
406 
407 // Instantiation of a static factory class used by clients to create
408 // instances of this service
410 
411 CLID EvtStoreSvc::rootCLID() const { return m_rootCLID; }
412 const std::string& EvtStoreSvc::rootName() const { return m_rootName; }
414  m_dataLoader = pDataLoader;
415  if ( m_dataLoader ) m_dataLoader->setDataProvider( dpsvc ? dpsvc : this ).ignore();
416  return StatusCode::SUCCESS;
417 }
419 size_t EvtStoreSvc::allocateStore( int evtnumber ) {
420  // take next free slot in the list
421  size_t slot = std::string::npos;
422  if ( m_freeSlots.try_pop( slot ) ) {
423  assert( slot != std::string::npos );
424  assert( slot < m_partitions.size() );
425  [[maybe_unused]] auto prev = m_partitions[slot].with_lock(
426  [evtnumber]( Partition& p ) { return std::exchange( p.eventNumber, evtnumber ); } );
427  assert( prev == -1 ); // or whatever value represents 'free'
428  }
429  return slot;
430 }
433  if ( slots < size_t{1} ) {
434  error() << "Invalid number of slots (" << slots << ")" << endmsg;
435  return StatusCode::FAILURE;
436  }
438  error() << "Too late to change the number of slots!" << endmsg;
439  return StatusCode::FAILURE;
440  }
441  m_slots = slots;
443  return StatusCode::SUCCESS;
444 }
446 size_t EvtStoreSvc::getPartitionNumber( int eventnumber ) const {
448  with_lock( [eventnumber]( const Partition& p ) { return p.eventNumber == eventnumber; } ) );
449  return i != end( m_partitions ) ? std::distance( begin( m_partitions ), i ) : std::string::npos;
450 }
453  s_current = &m_partitions[partition];
454  return StatusCode::SUCCESS;
455 }
457 StatusCode EvtStoreSvc::freeStore( size_t partition ) {
458  assert( partition < m_partitions.size() );
459  auto prev = m_partitions[partition].with_lock( []( Partition& p ) { return std::exchange( p.eventNumber, -1 ); } );
460  if ( UNLIKELY( prev == -1 ) ) return StatusCode::FAILURE; // double free -- should never happen!
461  m_freeSlots.push( partition );
462  return StatusCode::SUCCESS;
463 }
465 StatusCode EvtStoreSvc::clearStore( size_t partition ) {
466  m_onlyThisID = {};
467  return m_partitions[partition].with_lock( [this]( Partition& p ) {
468  fillStats( p );
469  initStore( p ); // replace with a clean store
470  return StatusCode::SUCCESS;
471  } );
472 }
474  top = normalize_path( top, rootName() );
475  return fwd( [&]( Partition& p ) {
476  p.store->erase_if( [top]( const auto& value ) { return boost::algorithm::starts_with( value.first, top ); } );
477  return StatusCode::SUCCESS;
478  } );
479 }
481  m_onlyThisID = {};
482  return fwd( [this]( Partition& p ) {
483  fillStats( p );
484  initStore( p ); // replace with a clean store
485  return StatusCode::SUCCESS;
486  } );
487 }
489  return fwd( [&]( Partition& p ) {
490  top = normalize_path( top, rootName() );
491  auto cmp = []( const Entry* lhs, const Entry* rhs ) { return lhs->identifier() < rhs->identifier(); };
492  std::set<const Entry*, decltype( cmp )> keys{std::move( cmp )};
493  for ( const auto& v : *p.store ) {
494  if ( boost::algorithm::starts_with( v.second.identifier(), top ) ) keys.insert( &v.second );
495  }
496  auto k = keys.begin();
497  while ( k != keys.end() ) {
498  const auto& id = ( *k )->identifier();
499  int level = std::count( id.begin(), id.end(), '/' );
500  bool accept = pAgent->analyse( const_cast<Entry*>( *( k++ ) ), level );
501  if ( !accept ) {
502  k = std::find_if_not( k, keys.end(),
503  [&id]( const auto& e ) { return boost::algorithm::starts_with( e->identifier(), id ); } );
504  }
505  }
506  return StatusCode::SUCCESS;
507  } );
508 }
510  if ( msgLevel( MSG::DEBUG ) ) {
511  debug() << "setRoot( " << root_path << ", (DataObject*)" << (void*)pObject << " )" << endmsg;
512  }
513  if ( UNLIKELY( !fwd( []( Partition& p ) {
514  return p.store->empty() ? StatusCode::SUCCESS : StatusCode::FAILURE;
515  } ).isSuccess() ) ) {
516  throw GaudiException{"setRoot called with non-empty store", "EvtStoreSvc", StatusCode::FAILURE};
517  }
518  return registerObject( nullptr, root_path, pObject );
519 }
521  auto rootAddr = std::unique_ptr<IOpaqueAddress>( pRootAddr );
522  if ( msgLevel( MSG::DEBUG ) ) {
523  debug() << "setRoot( " << root_path << ", (IOpaqueAddress*)" << rootAddr.get();
524  if ( rootAddr ) debug() << "[ " << rootAddr->par()[0] << ", " << rootAddr->par()[1] << " ]";
525  debug() << " )" << endmsg;
526  }
527  if ( UNLIKELY( !fwd( []( Partition& p ) {
528  return p.store->empty() ? StatusCode::SUCCESS : StatusCode::FAILURE;
529  } ).isSuccess() ) ) {
530  throw GaudiException{"setRoot called with non-empty store", "EvtStoreSvc", StatusCode::FAILURE};
531  }
532  if ( !rootAddr ) return Status::INVALID_OBJ_ADDR; // Precondition: Address must be valid
533  if ( !m_followLinksToAncestors ) m_onlyThisID = rootAddr->par()[0];
534  auto object = createObj( *m_dataLoader, *rootAddr ); // Call data loader
535  if ( !object ) return Status::INVALID_OBJECT;
536  if ( msgLevel( MSG::DEBUG ) ) { debug() << "Root Object " << root_path << " created " << endmsg; }
537  LocalArena dummy_arena{root_path.size() + 1};
538  auto dummy = Entry{root_path, {}, {}, &dummy_arena};
539  object->setRegistry( &dummy );
540  rootAddr->setRegistry( &dummy );
541  auto status = m_dataLoader->fillObjRefs( rootAddr.get(), object.get() );
542  if ( status.isSuccess() ) {
543  auto pObject = object.get();
544  status = registerObject( nullptr, root_path, object.release() );
545  if ( status.isSuccess() ) pObject->registry()->setAddress( rootAddr.release() );
546  }
547  return status;
548 }
550  return registerAddress( nullptr, path, pAddr );
551 }
553  auto addr = std::unique_ptr<IOpaqueAddress>( pAddr );
554  if ( !addr ) return Status::INVALID_OBJ_ADDR; // Precondition: Address must be valid
555  if ( msgLevel( MSG::DEBUG ) ) {
556  debug() << "registerAddress( (IRegistry*)" << (void*)pReg << ", " << path << ", (IOpaqueAddress*)" << addr.get()
557  << "[ " << addr->par()[0] << ", " << addr->par()[1] << " ]"
558  << " )" << endmsg;
559  }
560  if ( path.empty() || path[0] != '/' ) return StatusCode::FAILURE;
561  if ( !m_onlyThisID.empty() && addr->par()[0] != m_onlyThisID ) {
562  if ( msgLevel( MSG::DEBUG ) )
563  debug() << "Attempt to load " << addr->par()[1] << " from file " << addr->par()[0] << " blocked -- different file"
564  << endmsg;
565  return StatusCode::SUCCESS;
566  }
567  if ( std::any_of( m_inhibitPrefixes.begin(), m_inhibitPrefixes.end(),
568  [addrPath = addr->par()[1]]( std::string_view prefix ) {
569  return boost::algorithm::starts_with( addrPath, prefix );
570  } ) ) {
571  if ( msgLevel( MSG::DEBUG ) )
572  debug() << "Attempt to load " << addr->par()[1] << " from file " << addr->par()[0] << " blocked -- path inhibited"
573  << endmsg;
574  return StatusCode::SUCCESS;
575  }
576 
577  auto object = createObj( *m_dataLoader, *addr ); // Call data loader
578  if ( !object ) return Status::INVALID_OBJECT;
579  auto fullpath = ( pReg ? pReg->identifier() : m_rootName.value() ) + std::string{path};
580  // the data loader expects the path _including_ the root
581  LocalArena dummy_arena{fullpath.size() + 1};
582  auto dummy = Entry{fullpath, {}, {}, &dummy_arena};
583  object->setRegistry( &dummy );
584  addr->setRegistry( &dummy );
585  auto status = m_dataLoader->fillObjRefs( addr.get(), object.get() );
586  if ( !status.isSuccess() ) return status;
587  // note: put will overwrite the registry in pObject to point at the
588  // one actually used -- so we do not dangle, pointing at dummy beyond its
589  // lifetime
590  if ( msgLevel( MSG::DEBUG ) ) {
591  auto ptr = object.get();
592  debug() << "registerAddress: " << std::quoted( normalize_path( fullpath, rootName() ) ) << " (DataObject*)"
593  << static_cast<void*>( ptr ) << ( ptr ? " -> " + System::typeinfoName( typeid( *ptr ) ) : std::string{} )
594  << endmsg;
595  }
596  fwd( [&]( Partition& p ) {
597  p.store->put( normalize_path( fullpath, rootName() ), std::move( object ), std::move( addr ) );
598  return StatusCode::SUCCESS;
599  } ).ignore();
600  return status;
601 }
602 StatusCode EvtStoreSvc::registerObject( std::string_view parentPath, std::string_view objectPath,
603  DataObject* pObject ) {
604  return parentPath.empty()
605  ? registerObject( nullptr, objectPath, pObject )
606  : registerObject( nullptr, std::string{parentPath}.append( "/" ).append( objectPath ), pObject );
607 }
608 StatusCode EvtStoreSvc::registerObject( DataObject* parentObj, std::string_view path, DataObject* pObject ) {
609  if ( parentObj ) return StatusCode::FAILURE;
610  return fwd( [&, object = std::unique_ptr<DataObject>( pObject ),
611  path = normalize_path( path, rootName() )]( Partition& p ) mutable {
612  if ( m_forceLeaves ) {
613  auto dir = path;
614  for ( auto i = dir.rfind( '/' ); i != std::string_view::npos; i = dir.rfind( '/' ) ) {
615  dir = dir.substr( 0, i );
616  if ( !p.store->find( dir ) ) {
617  if ( msgLevel( MSG::DEBUG ) ) {
618  debug() << "registerObject: adding directory " << std::quoted( dir ) << endmsg;
619  }
620  p.store->put( dir, std::unique_ptr<DataObject>{} );
621  }
622  }
623  }
624  if ( msgLevel( MSG::DEBUG ) ) {
625  auto ptr = object.get();
626  debug() << "registerObject: " << std::quoted( path ) << " (DataObject*)" << static_cast<void*>( ptr )
627  << ( ptr ? " -> " + System::typeinfoName( typeid( *ptr ) ) : std::string{} ) << endmsg;
628  }
629  p.store->put( path, std::move( object ) );
630  return StatusCode::SUCCESS;
631  } );
632 }
633 StatusCode EvtStoreSvc::retrieveObject( IRegistry* pDirectory, std::string_view path, DataObject*& pObject ) {
634  if ( pDirectory ) return StatusCode::FAILURE;
635  return fwd( [&]( Partition& p ) {
636  path = normalize_path( path, rootName() );
637  pObject = const_cast<DataObject*>( p.store->get( path ) );
638  if ( msgLevel( MSG::DEBUG ) ) {
639  debug() << "retrieveObject: " << std::quoted( path ) << " (DataObject*)" << (void*)pObject
640  << ( pObject ? " -> " + System::typeinfoName( typeid( *pObject ) ) : std::string{} ) << endmsg;
641  }
642  return pObject ? StatusCode::SUCCESS : StatusCode::FAILURE;
643  } );
644 }
645 StatusCode EvtStoreSvc::findObject( IRegistry* pDirectory, std::string_view path, DataObject*& pObject ) {
646  return retrieveObject( pDirectory, path, pObject );
647 }
648 StatusCode EvtStoreSvc::findObject( std::string_view fullPath, DataObject*& pObject ) {
649  return retrieveObject( nullptr, fullPath, pObject );
650 }
652  return fwd( [&]( Partition& p ) { return p.store->erase( sr ) != 0 ? StatusCode::SUCCESS : StatusCode::FAILURE; } );
653 }
655  auto i = std::find( m_preLoads.begin(), m_preLoads.begin(), item );
656  if ( i == m_preLoads.end() ) m_preLoads.push_back( item );
657  return StatusCode::SUCCESS;
658 }
660  auto i = std::remove( m_preLoads.begin(), m_preLoads.begin(), item );
661  m_preLoads.erase( i, m_preLoads.end() );
662  return StatusCode::SUCCESS;
663 }
665  for ( const auto& i : m_preLoads ) {
666  DataObject* pObj;
667  if ( msgLevel( MSG::DEBUG ) ) debug() << "Preloading " << i.path() << endmsg;
668  retrieveObject( nullptr, i.path(), pObj ).ignore();
669  }
670  return StatusCode::SUCCESS;
671 }
MSG::DEBUG
@ DEBUG
Definition: IMessageSvc.h:25
EvtStoreSvc::freeSlots
size_t freeSlots() override
Definition: EvtStoreSvc.cpp:302
std::lock
T lock(T... args)
EvtStoreSvc::getPartitionNumber
size_t getPartitionNumber(int eventnumber) const override
Get the partition number corresponding to a given event.
Definition: EvtStoreSvc.cpp:446
EvtStoreSvc::traverseSubTree
StatusCode traverseSubTree(DataObject *obj, IDataStoreAgent *pAgent) override
Definition: EvtStoreSvc.cpp:325
std::basic_string
STL class.
std::equal
T equal(T... args)
EvtStoreSvc::linkObject
StatusCode linkObject(std::string_view, DataObject *) override
Definition: EvtStoreSvc.cpp:368
details::size
constexpr auto size(const T &, Args &&...) noexcept
Definition: AnyDataWrapper.h:22
IOpaqueAddress::par
virtual const std::string * par() const =0
Retrieve String parameters.
EvtStoreSvc::allocateStore
size_t allocateStore(int evtnumber) override
Allocate a store partition for a given event number.
Definition: EvtStoreSvc.cpp:419
EvtStoreSvc::m_onlyThisID
std::string_view m_onlyThisID
Definition: EvtStoreSvc.cpp:291
std::move
T move(T... args)
EvtStoreSvc::addPreLoadItem
StatusCode addPreLoadItem(const DataStoreItem &) override
Definition: EvtStoreSvc.cpp:654
EvtStoreSvc::removePreLoadItem
StatusCode removePreLoadItem(const DataStoreItem &) override
Definition: EvtStoreSvc.cpp:659
System.h
ReadAndWriteWhiteBoard.loader
loader
Definition: ReadAndWriteWhiteBoard.py:46
EvtStoreSvc::traverseSubTree
StatusCode traverseSubTree(std::string_view, IDataStoreAgent *) override
Definition: EvtStoreSvc.cpp:488
EvtStoreSvc::objectLeaves
StatusCode objectLeaves(const DataObject *, std::vector< IRegistry * > &) override
Definition: EvtStoreSvc.cpp:316
EvtStoreSvc::retrieveObject
StatusCode retrieveObject(IRegistry *pDirectory, std::string_view path, DataObject *&pObject) override
Definition: EvtStoreSvc.cpp:633
IDataStoreAgent::analyse
virtual bool analyse(IRegistry *pObject, int level)=0
Analyse the data object.
gaudirun.s
string s
Definition: gaudirun.py:328
IOpaqueAddress
Definition: IOpaqueAddress.h:33
EvtStoreSvc::unlinkObject
StatusCode unlinkObject(IRegistry *, std::string_view) override
Definition: EvtStoreSvc.cpp:369
EvtStoreSvc::m_usedPoolAllocations
Gaudi::Accumulators::AveragingCounter< std::size_t > m_usedPoolAllocations
Definition: EvtStoreSvc.cpp:247
std::vector< DataStoreItem >
EvtStoreSvc::updateObject
StatusCode updateObject(DataObject *) override
Definition: EvtStoreSvc.cpp:357
std::find
T find(T... args)
std::vector::size
T size(T... args)
EvtStoreSvc::clearSubTree
StatusCode clearSubTree(std::string_view) override
Definition: EvtStoreSvc.cpp:473
Monotonic.h
GaudiException
Definition: GaudiException.h:31
Gaudi::Accumulators::AveragingCounter< std::size_t >
EvtStoreSvc::resetPreLoad
StatusCode resetPreLoad() override
Definition: EvtStoreSvc.cpp:361
std::unique_ptr::get
T get(T... args)
std::distance
T distance(T... args)
EvtStoreSvc::unregisterAddress
StatusCode unregisterAddress(IRegistry *, std::string_view) override
Definition: EvtStoreSvc.cpp:334
ConcurrencyFlags.h
conf.release
string release
Definition: conf.py:28
IConverter::createObj
virtual StatusCode createObj(IOpaqueAddress *pAddress, DataObject *&refpObject)=0
Create the transient representation of an object.
gaudirun.prefix
string prefix
Definition: gaudirun.py:343
IRegistry
Definition: IRegistry.h:32
std::any_of
T any_of(T... args)
System::typeinfoName
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:308
EvtStoreSvc::objectParent
StatusCode objectParent(const IRegistry *, IRegistry *&) override
Definition: EvtStoreSvc.cpp:315
EvtStoreSvc::objectParent
StatusCode objectParent(const DataObject *, IRegistry *&) override
Definition: EvtStoreSvc.cpp:314
System::backTrace
GAUDI_API int backTrace(void **addresses, const int depth)
std::unique_ptr::reset
T reset(T... args)
CommonMessaging< implements< IService, IProperty, IStateful > >::msgLevel
MSG::Level msgLevel() const
get the cached level (originally extracted from the embedded MsgStream)
Definition: CommonMessaging.h:148
IDataProviderSvc.h
Service::FSMState
Gaudi::StateMachine::State FSMState() const override
Definition: Service.h:62
std::vector::clear
T clear(T... args)
EvtStoreSvc::freeStore
StatusCode freeStore(size_t partition) override
Free a store partition.
Definition: EvtStoreSvc.cpp:457
std::vector::push_back
T push_back(T... args)
EvtStoreSvc::fillStats
void fillStats(Partition &p) const
Definition: EvtStoreSvc.cpp:252
EvtStoreSvc
Definition: EvtStoreSvc.cpp:237
IRegistry::name
virtual const name_type & name() const =0
Name of the directory (or key)
IDataProviderSvc::Status::INVALID_ROOT
@ INVALID_ROOT
Invalid root path object cannot be retrieved or stored.
EvtStoreSvc::objectLeaves
StatusCode objectLeaves(const IRegistry *, std::vector< IRegistry * > &) override
Definition: EvtStoreSvc.cpp:317
Gaudi::Functional::details::get
auto get(const Handle &handle, const Algo &, const EventContext &) -> decltype(details::deref(handle.get()))
Definition: FunctionalDetails.h:391
EvtStoreSvc::unlinkObject
StatusCode unlinkObject(std::string_view) override
Definition: EvtStoreSvc.cpp:371
StatusCode
Definition: StatusCode.h:65
EvtStoreSvc::unregisterObject
StatusCode unregisterObject(DataObject *obj) override
Definition: EvtStoreSvc.cpp:342
EvtStoreSvc::updateObject
StatusCode updateObject(IRegistry *) override
Definition: EvtStoreSvc.cpp:356
HistoDumpEx.r
r
Definition: HistoDumpEx.py:20
EvtStoreSvc::unregisterObject
StatusCode unregisterObject(DataObject *obj, std::string_view sr) override
Definition: EvtStoreSvc.cpp:345
EvtStoreSvc::m_followLinksToAncestors
Gaudi::Property< bool > m_followLinksToAncestors
Definition: EvtStoreSvc.cpp:288
CLHEP::begin
double * begin(CLHEP::HepVector &v)
Definition: TupleAlg.cpp:45
DataStoreItem
Definition: DataStoreItem.h:27
Gaudi::Accumulators::AveragingAccumulatorBase::mean
auto mean() const
Definition: Accumulators.h:716
IOpaqueAddress.h
LIKELY
#define LIKELY(x)
Definition: Kernel.h:105
EvtStoreSvc::linkObject
StatusCode linkObject(IRegistry *, std::string_view, DataObject *) override
Definition: EvtStoreSvc.cpp:367
Gaudi::Property::value
const ValueType & value() const
Backward compatibility (.
Definition: Property.h:240
EvtStoreSvc::initStore
void initStore(Partition &p) const
Definition: EvtStoreSvc.cpp:264
GaudiPython.HistoUtils.path
path
Definition: HistoUtils.py:943
EvtStoreSvc::unregisterObject
StatusCode unregisterObject(std::string_view) override
Definition: EvtStoreSvc.cpp:651
EvtStoreSvc::m_preLoads
std::vector< DataStoreItem > m_preLoads
Items to be pre-loaded.
Definition: EvtStoreSvc.cpp:276
std::vector::erase
T erase(T... args)
std::runtime_error
STL class.
EvtStoreSvc::traverseTree
StatusCode traverseTree(IDataStoreAgent *pAgent) override
Definition: EvtStoreSvc.cpp:328
SmartIF< IConversionSvc >
std::logic_error
STL class.
IRegistry::release
virtual unsigned long release()=0
release reference to object
CLID
unsigned int CLID
Class ID definition.
Definition: ClassID.h:18
IHiveWhiteBoard.h
IRegistry::addRef
virtual unsigned long addRef()=0
Add reference to object.
IRegistry::setAddress
virtual void setAddress(IOpaqueAddress *pAddress)=0
Set/Update Opaque storage address.
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:203
std::remove
T remove(T... args)
std::map
STL class.
EvtStoreSvc::finalize
StatusCode finalize() override
Definition: EvtStoreSvc.cpp:395
extends
Base class used to extend a class implementing other interfaces.
Definition: extends.h:20
gaudirun.level
level
Definition: gaudirun.py:346
IRegistry.h
Gaudi::StateMachine::RUNNING
@ RUNNING
Definition: StateMachine.h:26
EvtStoreSvc::registerObject
StatusCode registerObject(std::string_view parentPath, std::string_view objectPath, DataObject *pObject) override
Definition: EvtStoreSvc.cpp:602
Gaudi::Arena::Monotonic
A fast memory arena that does not track deallocations.
Definition: Monotonic.h:46
DataObjID
Definition: DataObjID.h:47
EvtStoreSvc::preLoad
StatusCode preLoad() override
Definition: EvtStoreSvc.cpp:664
std::string::append
T append(T... args)
StatusCode::ignore
const StatusCode & ignore() const
Allow discarding a StatusCode without warning.
Definition: StatusCode.h:156
Service.h
HistoDumpEx.v
v
Definition: HistoDumpEx.py:27
EvtStoreSvc::rootName
const std::string & rootName() const override
Definition: EvtStoreSvc.cpp:412
std::equal_to
EvtStoreSvc::findObject
StatusCode findObject(IRegistry *pDirectory, std::string_view path, DataObject *&pObject) override
Definition: EvtStoreSvc.cpp:645
IRegistry::address
virtual IOpaqueAddress * address() const =0
Retrieve opaque storage address.
EvtStoreSvc::registerAddress
StatusCode registerAddress(std::string_view fullPath, IOpaqueAddress *pAddress) override
Definition: EvtStoreSvc.cpp:549
EvtStoreSvc::m_usedPoolSize
Gaudi::Accumulators::AveragingCounter< std::size_t > m_usedPoolSize
Definition: EvtStoreSvc.cpp:246
EvtStoreSvc::m_rootName
Gaudi::Property< std::string > m_rootName
Definition: EvtStoreSvc.cpp:239
EvtStoreSvc::exists
bool exists(const DataObjID &id) override
Definition: EvtStoreSvc.cpp:309
Accumulators.h
TTHREAD_TLS
TTHREAD_TLS(Synced< Partition > *) s_current
EvtStoreSvc::clearSubTree
StatusCode clearSubTree(DataObject *obj) override
Definition: EvtStoreSvc.cpp:320
EvtStoreSvc::m_freeSlots
tbb::concurrent_queue< size_t > m_freeSlots
Definition: EvtStoreSvc.cpp:281
IOpaqueAddress::setRegistry
virtual void setRegistry(IRegistry *r)=0
Update directory pointer.
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
SmartIF::get
TYPE * get() const
Get interface pointer.
Definition: SmartIF.h:86
Gaudi::Units::sr
constexpr double sr
Definition: SystemOfUnits.h:132
EvtStoreSvc::selectStore
StatusCode selectStore(size_t partition) override
Activate a partition object. The identifies the partition uniquely.
Definition: EvtStoreSvc.cpp:452
std::vector::begin
T begin(T... args)
Gaudi::Allocator::Arena
Custom allocator holding a pointer to a generic memory resource.
Definition: Arena.h:29
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:46
EvtStoreSvc::setDataLoader
StatusCode setDataLoader(IConversionSvc *svc, IDataProviderSvc *dpsvc) override
Definition: EvtStoreSvc.cpp:413
Gaudi::StateMachine::INITIALIZED
@ INITIALIZED
Definition: StateMachine.h:25
IRegistry::object
virtual DataObject * object() const =0
Retrieve object behind the link.
DataObject
Definition: DataObject.h:40
IRegistry::identifier
virtual const id_type & identifier() const =0
Full identifier (or key)
EvtStoreSvc::m_partitions
std::vector< Synced< Partition > > m_partitions
The actual store(s)
Definition: EvtStoreSvc.cpp:279
std::count
T count(T... args)
EvtStoreSvc::getNumberOfStores
size_t getNumberOfStores() const override
Definition: EvtStoreSvc.cpp:307
std::size_t
EvtStoreSvc::m_forceLeaves
Gaudi::Property< bool > m_forceLeaves
Definition: EvtStoreSvc.cpp:240
EvtStoreSvc::setRoot
StatusCode setRoot(std::string root_name, DataObject *pObject) override
Definition: EvtStoreSvc.cpp:509
Gaudi::Concurrency::ConcurrencyFlags::setNumConcEvents
static GAUDI_API void setNumConcEvents(const std::size_t &nE)
Definition: ConcurrencyFlags.h:69
std::vector::end
T end(T... args)
IDataProviderSvc
Definition: IDataProviderSvc.h:53
IOTest.end
end
Definition: IOTest.py:123
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
EvtStoreSvc::m_slots
Gaudi::Property< size_t > m_slots
Definition: EvtStoreSvc.cpp:242
IConversionSvc.h
EvtStoreSvc::unregisterAddress
StatusCode unregisterAddress(std::string_view) override
Definition: EvtStoreSvc.cpp:333
UNLIKELY
#define UNLIKELY(x)
Definition: Kernel.h:106
EvtStoreSvc::m_inhibitPrefixes
Gaudi::Property< std::vector< std::string > > m_inhibitPrefixes
Definition: EvtStoreSvc.cpp:283
EvtStoreSvc::initialize
StatusCode initialize() override
Definition: EvtStoreSvc.cpp:373
AlgSequencer.top
top
Definition: AlgSequencer.py:31
EvtStoreSvc::clearStore
StatusCode clearStore() override
Definition: EvtStoreSvc.cpp:480
EvtStoreSvc::setNumberOfStores
StatusCode setNumberOfStores(size_t slots) override
Set the number of event slots (copies of DataSvc objects).
Definition: EvtStoreSvc.cpp:432
EvtStoreSvc::unlinkObject
StatusCode unlinkObject(DataObject *, std::string_view) override
Definition: EvtStoreSvc.cpp:370
std::unique_ptr
STL class.
EvtStoreSvc::poolSize
std::size_t poolSize() const
Definition: EvtStoreSvc.cpp:250
std::unordered_map
STL class.
DataObject::registry
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:82
std::set
STL class.
GAUDI_API
#define GAUDI_API
Definition: Kernel.h:81
Gaudi::Property< CLID >
IRegistry::dataSvc
virtual IDataProviderSvc * dataSvc() const =0
Retrieve pointer to Transient Store.
IDataManagerSvc.h
Gaudi::Functional::details::put
auto put(const DataObjectHandle< Out1 > &out_handle, Out2 &&out)
Definition: FunctionalDetails.h:147
IDataStoreAgent
Definition: IDataStoreAgent.h:27
StringKeyEx.keys
list keys
Definition: StringKeyEx.py:67
IConversionSvc
Definition: IConversionSvc.h:47
EvtStoreSvc::m_dataLoader
SmartIF< IConversionSvc > m_dataLoader
Definition: EvtStoreSvc.cpp:273