ATLAS Offline Software
Loading...
Searching...
No Matches
Athena::DelayedConditionsCleanerSvc Class Reference

Clean conditions containers after a delay. More...

#include <DelayedConditionsCleanerSvc.h>

Inheritance diagram for Athena::DelayedConditionsCleanerSvc:
Collaboration diagram for Athena::DelayedConditionsCleanerSvc:

Classes

class  CondContInfo
 Information that we maintain about each conditions container. More...
struct  QueueItem
 Item in the work queue. More...

Public Types

typedef CondContBase::key_type key_type
 Packed key type.

Public Member Functions

 DelayedConditionsCleanerSvc (const std::string &name, ISvcLocator *svc)
 Standard Gaudi constructor.
 ~DelayedConditionsCleanerSvc ()
 Standard destructor.
virtual StatusCode initialize () override
 Standard Gaudi initialize method.
virtual StatusCode finalize () override
 Standard Gaudi finalize method.
virtual StatusCode event (const EventContext &ctx, bool allowAsync) override
 Called at the start of each event.
virtual StatusCode condObjAdded (const EventContext &ctx, CondContBase &cc) override
 Called after a conditions object has been added.
virtual StatusCode printStats () const override
 Print some statistics about the garbage collection.
virtual StatusCode reset () override
 Clear the internal state of the service.

Private Types

typedef CxxUtils::Ring< key_typeRing
 Ring buffer holding most recent IOV keys of a given type.
using KeyType = CondContBase::KeyType
 Run+LBN or timestamp key?
typedef std::array< std::vector< key_type >, 2 > twoKeys_t
typedef std::unordered_map< CondContBase *, CondContInfoCCInfoMap_t
 Map of information, indexed by the conditions container.
typedef std::mutex mutex_t
 Serialize access to m_ccinfo and m_work.
typedef std::lock_guard< mutex_tlock_t

Private Member Functions

twoKeys_t getKeys (const Ring &runLBRing, const Ring &TSRing) const
void scheduleClean (std::vector< CondContInfo * > &&cis, twoKeys_t &&twoKeys, bool allowAsync)
 Do cleaning for a set of containers.
void cleanContainers (std::vector< CondContInfo * > &&cis, twoKeys_t &&twoKeys)
 Clean a set of containers.
bool cleanContainer (CondContInfo *ci, const twoKeys_t &keys) const
 Clean a single container.

Private Attributes

Ring m_runlbn
 Two ring buffers for recent IOV keys, one for run+LBN and one for timestamp.
Ring m_timestamp
std::vector< key_typem_slotLBN
 IOV keys currently in use for each slot.
std::vector< key_typem_slotTimestamp
CCInfoMap_t m_ccinfo
std::priority_queue< QueueItemm_work
 Priority queue of pending cleaning requests.
mutex_t m_workMutex
size_t m_nEvents = 0
 Priority queue statistics.
size_t m_queueSum = 0
size_t m_workRemoved = 0
size_t m_maxQueue = 0
std::atomic< int > m_cleanTasks {0}
 Number of active asynchronous cleaning tasks.
std::unique_ptr< DelayedConditionsCleanerSvcPropsm_props
 Component properties.

Friends

class DelayedConditionsCleanerTask

Detailed Description

Clean conditions containers after a delay.

This is an implementation of IConditionsCleanerSvc, for doing garbage collection of conditions objects.

Briefly, it works like this.

When a conditions object is added (condObjAdded interface), we put an entry in a priority queue, saying that we want to clean this container CleanDelay events later.

On each event (event interface) we put the current IOV keys (run+LBN and timestamp) into ring buffers (of size RingSize). If the topmost entry of the priority queue has come due, then we pull off that entry and other entries due up to LookAhead events later. We then do a trim operation on each of the conditions containers, removing conditions objects from the oldest first that do not match any of the IOV keys in the ring buffer.

The cleaning can optionally be done as an asynchronous TBB job if Async is true and allowAsync=true is passed to event.

Definition at line 57 of file DelayedConditionsCleanerSvc.h.

Member Typedef Documentation

◆ CCInfoMap_t

Map of information, indexed by the conditions container.

Definition at line 214 of file DelayedConditionsCleanerSvc.h.

◆ key_type

◆ KeyType

Run+LBN or timestamp key?

Definition at line 133 of file DelayedConditionsCleanerSvc.h.

◆ lock_t

typedef std::lock_guard<mutex_t> Athena::DelayedConditionsCleanerSvc::lock_t
private

Definition at line 241 of file DelayedConditionsCleanerSvc.h.

◆ mutex_t

Serialize access to m_ccinfo and m_work.

Definition at line 240 of file DelayedConditionsCleanerSvc.h.

◆ Ring

Ring buffer holding most recent IOV keys of a given type.

Definition at line 129 of file DelayedConditionsCleanerSvc.h.

◆ twoKeys_t

typedef std::array<std::vector<key_type>,2> Athena::DelayedConditionsCleanerSvc::twoKeys_t
private

Definition at line 135 of file DelayedConditionsCleanerSvc.h.

Constructor & Destructor Documentation

◆ DelayedConditionsCleanerSvc()

Athena::DelayedConditionsCleanerSvc::DelayedConditionsCleanerSvc ( const std::string & name,
ISvcLocator * svc )

Standard Gaudi constructor.

Parameters
nameService name.
svcService locator.

Definition at line 155 of file DelayedConditionsCleanerSvc.cxx.

157 : base_class (name, svc),
158 m_props (std::make_unique<DelayedConditionsCleanerSvcProps> (this))
159{
160}
std::unique_ptr< DelayedConditionsCleanerSvcProps > m_props
Component properties.

◆ ~DelayedConditionsCleanerSvc()

Athena::DelayedConditionsCleanerSvc::~DelayedConditionsCleanerSvc ( )

Standard destructor.

Needed to avoid problems with unique_ptr

Definition at line 493 of file DelayedConditionsCleanerSvc.cxx.

493{}

Member Function Documentation

◆ cleanContainer()

bool Athena::DelayedConditionsCleanerSvc::cleanContainer ( CondContInfo * ci,
const twoKeys_t & twoKeys ) const
private

Clean a single container.

Parameters
ciThe container to clean.
keysSet of IOV keys for recent events.

Returns true if anything was removed from the container,

Parameters
ciThe container to clean.
keyTypeRun+LBN or timestamp keys?
keysSet of IOV keys for recent events.

Returns true if anything was removed from the container,

Definition at line 468 of file DelayedConditionsCleanerSvc.cxx.

470{
471 size_t n = ci->m_cc.trim (twoKeys[0],twoKeys[1]);
472
473 ++ci->m_nClean;
474 ci->m_nRemoved += n;
475 switch (n) {
476 case 0:
477 ++ci->m_removed0;
478 break;
479 case 1:
480 ++ci->m_removed1;
481 break;
482 default:
483 ++ci->m_removed2plus;
484 }
485
486 return n > 0;
487}

◆ cleanContainers()

void Athena::DelayedConditionsCleanerSvc::cleanContainers ( std::vector< CondContInfo * > && cis,
twoKeys_t && twoKeys )
private

Clean a set of containers.

Parameters
cisSet of containers to clean.
keysSet of IOV keys for recent events.

Definition at line 423 of file DelayedConditionsCleanerSvc.cxx.

425{
426 // FIXME: Some conditions objects have pointers to parts of other
427 // conditions objects, which violates the lifetime guarantees of
428 // conditions containers (a pointer you get from a conditions container
429 // is guaranteed to be valid until the end of the current event, but
430 // not past that). In some cases, this can be dealt with by replacing
431 // the pointers with CondLink, but that is sometimes rather inconvenient.
432 // Try to work around this for now by ensuring that when we delete an object,
433 // we also try to clean the containers of other objects that may depend
434 // on it.
435 std::vector<CondContInfo*> toclean = std::move (cis);
436 std::unordered_set<CondContInfo*> cleaned (toclean.begin(), toclean.end());
437 while (!toclean.empty()) {
438 std::vector<CondContInfo*> newclean;
439 for (CondContInfo* ci : toclean) {
440 if (cleanContainer (ci, twoKeys)) {
441 lock_t lock (m_workMutex);
442 for (CondContBase* dep : ci->m_cc.getDeps()) {
443 CCInfoMap_t::iterator it = m_ccinfo.find (dep);
444 // If we don't find it, then dep must have no conditions objects.
445 if (it != m_ccinfo.end()) {
446 CondContInfo* ci_dep = &it->second;
447 if (cleaned.insert (ci_dep).second) {
448 newclean.push_back (ci_dep);
449 }
450 }
451 }
452 }
453 }
454 toclean = std::move (newclean);
455 }
456}
Information that we maintain about each conditions container.
bool cleanContainer(CondContInfo *ci, const twoKeys_t &keys) const
Clean a single container.

◆ condObjAdded()

StatusCode Athena::DelayedConditionsCleanerSvc::condObjAdded ( const EventContext & ctx,
CondContBase & cc )
overridevirtual

Called after a conditions object has been added.

Parameters
ctxThe current event context.
ccThe container to which the object was added.

Definition at line 256 of file DelayedConditionsCleanerSvc.cxx.

258{
259 // Add this container to the priority queue.
260 lock_t lock (m_workMutex);
261 CCInfoMap_t::iterator it = m_ccinfo.find (&cc);
262 if (it == m_ccinfo.end()) {
263 it = m_ccinfo.emplace (&cc, CondContInfo (cc)).first;
264 }
265
266 EventContext::ContextEvt_t evt = ctx.evt();
267 m_work.emplace (evt + m_props->m_cleanDelay, it->second);
268 return StatusCode::SUCCESS;
269}
std::priority_queue< QueueItem > m_work
Priority queue of pending cleaning requests.

◆ event()

StatusCode Athena::DelayedConditionsCleanerSvc::event ( const EventContext & ctx,
bool allowAsync )
overridevirtual

Called at the start of each event.

Parameters
ctxThe current event context.
allowAsyncIf true, then cleaning may be run in an asynchronous TBB task.

Definition at line 188 of file DelayedConditionsCleanerSvc.cxx.

189{
190 // Push the IOV key for the current event into the ring buffers.
191 // Also save in the per-slot arrays.
192 key_type key_lbn = CondContBase::keyFromRunLBN (ctx.eventID());
193 key_type key_ts = CondContBase::keyFromTimestamp (ctx.eventID());
194 m_runlbn.push (key_lbn);
195 m_timestamp.push (key_ts);
196 EventContext::ContextID_t slot = ctx.slot();
197 if (slot != EventContext::INVALID_CONTEXT_ID) {
198 m_slotLBN[slot] = key_lbn;
199 m_slotTimestamp[slot] = key_ts;
200 }
201
202 // Return now if an asynchronous cleaning task is still running ---
203 // we don't want to start a new one yet. We'll check pending work
204 // on the next call.
205 if (m_cleanTasks > 0) {
206 return StatusCode::SUCCESS;
207 }
208
209 // Collect conditions containers in need of cleaning.
210 std::vector<CondContInfo*> ci_vec;
211 {
212 lock_t lock (m_workMutex);
213 // Is it time to clean the container at the top of the work queue?
214 if (!m_work.empty() && m_work.top().m_evt <= ctx.evt()) {
215 ++m_nEvents;
216 size_t sz = m_work.size();
217 m_queueSum += sz;
218 m_maxQueue = std::max (m_maxQueue, sz);
219
220 // Yes. Put it on the correct list. Also look ahead in the queue
221 // a bit; if there are other containers that we want to clean soon,
222 // go ahead and do them now.
223 do {
224 CondContInfo* ci = m_work.top().m_ci;
225 switch (ci->m_cc.keyType()) {
226 case KeyType::SINGLE:
227 break;
228 case KeyType::RUNLBN:
229 case KeyType::MIXED:
230 case KeyType::TIMESTAMP:
231 ci_vec.push_back (ci);
232 break;
233 default:
234 std::abort();
235 }
236 m_work.pop();
238 } while (!m_work.empty() && m_work.top().m_evt <= ctx.evt() + m_props->m_lookAhead);
239 }
240 }
241
242 // Clean the containers.
243 if (!ci_vec.empty()) {
244 scheduleClean (std::move (ci_vec), getKeys(m_runlbn,m_timestamp),
245 allowAsync);
246 }
247 return StatusCode::SUCCESS;
248}
size_t m_nEvents
Priority queue statistics.
twoKeys_t getKeys(const Ring &runLBRing, const Ring &TSRing) const
Ring m_runlbn
Two ring buffers for recent IOV keys, one for run+LBN and one for timestamp.
void scheduleClean(std::vector< CondContInfo * > &&cis, twoKeys_t &&twoKeys, bool allowAsync)
Do cleaning for a set of containers.
CondContBase::key_type key_type
Packed key type.
std::atomic< int > m_cleanTasks
Number of active asynchronous cleaning tasks.
std::vector< key_type > m_slotLBN
IOV keys currently in use for each slot.
static key_type keyFromTimestamp(const EventIDBase &b)
Make a timestamp key from an EventIDBase.
static key_type keyFromRunLBN(const EventIDBase &b)
Make a run+lbn key from an EventIDBase.

◆ finalize()

StatusCode Athena::DelayedConditionsCleanerSvc::finalize ( )
overridevirtual

Standard Gaudi finalize method.

Definition at line 498 of file DelayedConditionsCleanerSvc.cxx.

499{
501 return StatusCode::SUCCESS;
502}
#define ATH_CHECK
Evaluate an expression and check for errors.
virtual StatusCode printStats() const override
Print some statistics about the garbage collection.

◆ getKeys()

DelayedConditionsCleanerSvc::twoKeys_t Athena::DelayedConditionsCleanerSvc::getKeys ( const Ring & runLBRing,
const Ring & TSRing ) const
private

Sort the key array and remove duplicates. We expect that the key array is probably ‘almost’ sorted. std::sort, at least in the gcc implementation, is designed to perform well in such cases.

Definition at line 345 of file DelayedConditionsCleanerSvc.cxx.

345 {
346
347 // Get a copy of the contents of the ring buffer holding runLumi and time-stamp keys
348 std::vector<key_type> runLBKeys=runLBRing.getKeysDedup();
349 std::vector<key_type> TSKeys=TSRing.getKeysDedup();
350
351 // Add in the keys for the currently-executing slots.
352 // These are very likely to already be in the ring, but that's
353 // not absolutely guaranteed.
354 // FIXME: This probably does another memory allocation, due to
355 // growing the buffer. Would be nice to avoid that.
356 runLBKeys.insert (runLBKeys.end(), m_slotLBN.begin(), m_slotLBN.end());
357 TSKeys.insert(TSKeys.end(), m_slotTimestamp.begin(), m_slotTimestamp.end());
358
359 twoKeys_t result{std::move(runLBKeys), std::move(TSKeys)};
360
365 for ( auto& keys : result ) {
366 std::sort (keys.begin(), keys.end());
367 auto end = std::unique (keys.begin(), keys.end());
368 keys.resize (end - keys.begin());
369 }
370
371
372 return result;
373}
std::array< std::vector< key_type >, 2 > twoKeys_t
DataModel_detail::iterator< DVL > unique(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of unique for DataVector/List.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.

◆ initialize()

StatusCode Athena::DelayedConditionsCleanerSvc::initialize ( )
overridevirtual

Standard Gaudi initialize method.

Definition at line 166 of file DelayedConditionsCleanerSvc.cxx.

167{
168 // Set the ring buffer sizes.
169 m_runlbn.reset (m_props->m_ringSize);
170 m_timestamp.reset (m_props->m_ringSize);
171
172 ATH_CHECK( m_props->m_rcu.retrieve() );
173 size_t nslots = m_props->m_rcu->getNumSlots();
174 m_slotLBN.resize (nslots);
175 m_slotTimestamp.resize (nslots);
176
177 return StatusCode::SUCCESS;
178}

◆ printStats()

StatusCode Athena::DelayedConditionsCleanerSvc::printStats ( ) const
overridevirtual

Print some statistics about the garbage collection.

Would generally be called in finalize(), but broken out as a separate interface for testing/debugging purposes.

Definition at line 277 of file DelayedConditionsCleanerSvc.cxx.

278{
279 // Suppress output if we didn't actually do anything.
280 if (m_nEvents == 0) {
281 return StatusCode::SUCCESS;
282 }
283
284 ATH_MSG_INFO( "Conditions container statistics" );
285 ATH_MSG_INFO( CxxUtils::strformat (" Work q: Max size: %zu (%zu queries) ",
287 size_t den = std::max (m_nEvents, 1lu);
288 ATH_MSG_INFO( CxxUtils::strformat (" Avg size: %.2f / Avg removed: %.2f",
289 static_cast<float>(m_queueSum)/den,
290 static_cast<float>(m_workRemoved)/den) );
291
292 std::vector<const CondContInfo*> infos;
293 for (const auto& p : m_ccinfo) {
294 infos.push_back (&p.second);
295 }
296 std::sort (infos.begin(), infos.end(),
297 [](const CondContInfo* a, const CondContInfo* b)
298 { return a->m_cc.id().key() < b->m_cc.id().key(); });
299
300 for (const CondContInfo* ci : infos) {
301 ATH_MSG_INFO( CxxUtils::strformat (" %-20s nInserts %6zu maxSize %3zu",
302 ci->m_cc.id().key().c_str(),
303 ci->m_cc.nInserts(),
304 ci->m_cc.maxSize()) );
305 den = std::max (ci->m_nClean, 1lu);
306 ATH_MSG_INFO( CxxUtils::strformat (" nClean %zu avgRemoved %.2f 0/1/2+ %zu/%zu/%zu",
307 ci->m_nClean,
308 static_cast<float> (ci->m_nRemoved) / den,
309 ci->m_removed0,
310 ci->m_removed1,
311 ci->m_removed2plus) );
312 }
313
314 return StatusCode::SUCCESS;
315}
#define ATH_MSG_INFO(x)
TList * a
std::string strformat(const char *fmt,...)
return a std::string according to a format fmt and varargs
Definition StrFormat.cxx:49

◆ reset()

StatusCode Athena::DelayedConditionsCleanerSvc::reset ( )
overridevirtual

Clear the internal state of the service.

Only for testing. Don't call if any other thread may be touching the service.

Definition at line 322 of file DelayedConditionsCleanerSvc.cxx.

323{
324 m_runlbn.reset (m_props->m_ringSize);
325 m_timestamp.reset (m_props->m_ringSize);
326
327 std::fill (m_slotLBN.begin(), m_slotLBN.end(), 0);
328 std::fill (m_slotTimestamp.begin(), m_slotTimestamp.end(), 0);
329
330 m_ccinfo.clear();
331 std::priority_queue<QueueItem> tmp;
332 m_work.swap (tmp);
333
334 m_nEvents = 0;
335 m_queueSum = 0;
336 m_workRemoved = 0;
337 m_maxQueue = 0;
338 m_cleanTasks = 0;
339
340 return StatusCode::SUCCESS;
341}

◆ scheduleClean()

void Athena::DelayedConditionsCleanerSvc::scheduleClean ( std::vector< CondContInfo * > && cis,
twoKeys_t && twoKeys,
bool allowAsync )
private

Do cleaning for a set of containers.

Parameters
cisSet of containers to clean.
ringRing buffer with recent IOV keys.
slotKeysVector of current keys for all slots.
allowAsyncCan this task run asynchronously?

This will either run cleaning directly, or submit it as a TBB task.

Definition at line 386 of file DelayedConditionsCleanerSvc.cxx.

389{
390 // Remove any duplicates from the list of containers.
391 std::sort (cis.begin(), cis.end());
392 auto pos = std::unique (cis.begin(), cis.end());
393 cis.resize (pos - cis.begin());
394
395 if (allowAsync && m_props->m_async) {
396#if USE_ASYNC_TASK
397 // Queue cleaning as a TBB task.
398 // Count that we have another executing task.
399 ++m_cleanTasks;
400
401 // Create the TBB task and queue it.
402 // TBB will delete the task object after it completes.
403 tbb::task* t = new (tbb::task::allocate_root())
404 DelayedConditionsCleanerTask (*this, std::move (cis),
405 std::move (twoKeys));
406 tbb::task::enqueue (*t);
407#endif
408 }
409 else
410 {
411 // Call cleaning directly.
412 cleanContainers (std::move (cis), std::move (twoKeys));
413 }
414}
void cleanContainers(std::vector< CondContInfo * > &&cis, twoKeys_t &&twoKeys)
Clean a set of containers.

◆ DelayedConditionsCleanerTask

friend class DelayedConditionsCleanerTask
friend

Definition at line 125 of file DelayedConditionsCleanerSvc.h.

Member Data Documentation

◆ m_ccinfo

CCInfoMap_t Athena::DelayedConditionsCleanerSvc::m_ccinfo
private

Definition at line 215 of file DelayedConditionsCleanerSvc.h.

◆ m_cleanTasks

std::atomic<int> Athena::DelayedConditionsCleanerSvc::m_cleanTasks {0}
private

Number of active asynchronous cleaning tasks.

Definition at line 253 of file DelayedConditionsCleanerSvc.h.

253{0};

◆ m_maxQueue

size_t Athena::DelayedConditionsCleanerSvc::m_maxQueue = 0
private

Definition at line 249 of file DelayedConditionsCleanerSvc.h.

◆ m_nEvents

size_t Athena::DelayedConditionsCleanerSvc::m_nEvents = 0
private

Priority queue statistics.

Definition at line 246 of file DelayedConditionsCleanerSvc.h.

◆ m_props

std::unique_ptr<DelayedConditionsCleanerSvcProps> Athena::DelayedConditionsCleanerSvc::m_props
private

Component properties.

Definition at line 256 of file DelayedConditionsCleanerSvc.h.

◆ m_queueSum

size_t Athena::DelayedConditionsCleanerSvc::m_queueSum = 0
private

Definition at line 247 of file DelayedConditionsCleanerSvc.h.

◆ m_runlbn

Ring Athena::DelayedConditionsCleanerSvc::m_runlbn
private

Two ring buffers for recent IOV keys, one for run+LBN and one for timestamp.

We only access these from event(), which is called from the event loop, so no locking is needed.

Definition at line 205 of file DelayedConditionsCleanerSvc.h.

◆ m_slotLBN

std::vector<key_type> Athena::DelayedConditionsCleanerSvc::m_slotLBN
private

IOV keys currently in use for each slot.

Definition at line 209 of file DelayedConditionsCleanerSvc.h.

◆ m_slotTimestamp

std::vector<key_type> Athena::DelayedConditionsCleanerSvc::m_slotTimestamp
private

Definition at line 210 of file DelayedConditionsCleanerSvc.h.

◆ m_timestamp

Ring Athena::DelayedConditionsCleanerSvc::m_timestamp
private

Definition at line 206 of file DelayedConditionsCleanerSvc.h.

◆ m_work

std::priority_queue<QueueItem> Athena::DelayedConditionsCleanerSvc::m_work
private

Priority queue of pending cleaning requests.

Definition at line 237 of file DelayedConditionsCleanerSvc.h.

◆ m_workMutex

mutex_t Athena::DelayedConditionsCleanerSvc::m_workMutex
mutableprivate

Definition at line 242 of file DelayedConditionsCleanerSvc.h.

◆ m_workRemoved

size_t Athena::DelayedConditionsCleanerSvc::m_workRemoved = 0
private

Definition at line 248 of file DelayedConditionsCleanerSvc.h.


The documentation for this class was generated from the following files: