VirtualBox

source: vbox/trunk/src/VBox/Main/src-all/ObjectsTracker.cpp@ 106882

Last change on this file since 106882 was 106882, checked in by vboxsync, 3 months ago

Fixed implicit conversions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.3 KB
Line 
1/* $Id: ObjectsTracker.cpp 106882 2024-11-08 08:54:51Z vboxsync $ */
2/** @file
3 * VirtualBox Object tracker implementation
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#define LOG_GROUP LOG_GROUP_MAIN
29
30#include "LoggingNew.h"
31#include "VirtualBoxBase.h"
32#include "ObjectsTracker.h"
33#include <iprt/log.h>
34#include <iprt/stream.h>
35#include <iprt/time.h>
36# include <iprt/asm.h>
37
38typedef std::unordered_map<std::string, TrackedObjectData>::const_iterator cIterTrObjDataType;
39typedef std::unordered_map<std::string, TrackedObjectData>::iterator iterTrObjDataType;
40
41/////////////////////////////////////////////////////////////////////////////
42// TrackedObjectData
43/////////////////////////////////////////////////////////////////////////////
44TrackedObjectData::TrackedObjectData():
45 m_componentName("noname"),
46 m_lifeTime(0),
47 m_idleTime(1),
48 m_State(TrackedObjectData::Invalid),
49 m_pIface(NULL)
50 {
51}
52
53TrackedObjectData::TrackedObjectData(const com::Guid &aObjId,
54 const com::Guid &aClassIID,
55 uint64_t aLifeTime,
56 uint64_t aIdleTime,
57 IUnknown* aPtr):
58
59 m_objId(aObjId),
60 m_classIID(aClassIID),
61 m_componentName("noname"),
62 m_lifeTime(aLifeTime),
63 m_idleTime(aIdleTime),
64 m_fIdleTimeStart(false),
65 m_pIface(aPtr)
66{
67 RTTimeNow(unconst(&m_creationTime));
68 m_lastAccessTime = m_creationTime;
69 m_State = TrackedObjectData::Valid;
70 Log2(("%s constructor \n", __FUNCTION__));
71}
72
73TrackedObjectData::~TrackedObjectData()
74{
75 Log2(("%s destructor\n", __FUNCTION__));
76 Log2(("DELETED Object %s (class IID %s)\n",
77 m_objId.toString().c_str(),
78 m_classIID.toString().c_str()
79 ));
80}
81
82TrackedObjectData &TrackedObjectData::operator=(const TrackedObjectData & that)
83{
84 LogFlowFuncEnter();
85 if (this != &that)
86 {
87 m_objId = that.m_objId;
88 m_classIID = that.m_classIID;
89 m_componentName = that.m_componentName;
90 m_lifeTime = that.m_lifeTime;
91 m_idleTime = that.m_idleTime;
92 m_pIface = that.m_pIface;
93 m_creationTime = that.m_creationTime;
94 m_lastAccessTime = that.m_lastAccessTime;
95 m_idleTimeStart = that.m_idleTimeStart;
96 m_fIdleTimeStart = that.m_fIdleTimeStart;
97 m_State = that.m_State;
98 }
99
100 return *this;
101}
102
103com::Utf8Str TrackedObjectData::updateLastAccessTime()
104{
105 RTTimeNow(unconst(&m_lastAccessTime));
106
107 char szTime[42];
108 RTTimeSpecToString(&m_lastAccessTime, szTime, sizeof(szTime));
109 return com::Utf8Str(szTime);
110}
111
112com::Utf8Str TrackedObjectData::initIdleTime()
113{
114 if (!m_fIdleTimeStart)
115 {
116 RTTimeNow(unconst(&m_idleTimeStart));
117 m_fIdleTimeStart = true;
118 }
119
120 char szTime[42];
121 RTTimeSpecToString(&m_idleTimeStart, szTime, sizeof(szTime));
122 return com::Utf8Str(szTime);
123}
124
125com::Utf8Str TrackedObjectData::creationTimeStr() const
126{
127 char szCreationTime[42];
128 RTTimeSpecToString(&m_creationTime, szCreationTime, sizeof(szCreationTime));
129
130 return com::Utf8Str(szCreationTime);
131}
132
133/* No locking here, be aware */
134unsigned long TrackedObjectData::i_checkRefCount(const Guid& aIID)
135{
136 ULONG cRefs = 0;
137 if (aIID == m_classIID)
138 {
139 m_pIface->AddRef();
140 cRefs = m_pIface->Release();
141
142 Log2(("**** Object %s (class IID %s) (refcount %lu) ****\n",
143 m_objId.toString().c_str(),
144 m_classIID.toString().c_str(),
145 cRefs
146 ));
147 }
148 return cRefs;
149}
150
151/////////////////////////////////////////////////////////////////////////////
152// TrackedObjectsCollector
153/////////////////////////////////////////////////////////////////////////////
154class TrackedObjectsCollector;
155extern TrackedObjectsCollector gTrackedObjectsCollector;
156
157TrackedObjectsCollector::TrackedObjectsCollector(): m_fInitialized(false)
158{
159 Log2(("%s constructor \n", __FUNCTION__));
160}
161
162TrackedObjectsCollector::~TrackedObjectsCollector()
163{
164 Log2(("%s destructor \n", __FUNCTION__));
165
166 int vrc = i_checkInitialization();
167
168 /*
169 * Someone forgot to call uninit()
170 */
171 if (RT_SUCCESS(vrc))
172 {
173 if (m_trackedObjectsData.size() != 0)
174 {
175 if (m_trackedObjectsData.size() > 1)
176 LogRel(("%u objects are still presented in the collector\n", m_trackedObjectsData.size()));
177 else
178 LogRel(("%u object is still presented in the collector\n", m_trackedObjectsData.size()));
179
180 m_Released += m_trackedObjectsData.size();
181 m_trackedObjectsData.clear();
182 }
183
184 LogRel(("The Objects Collector history data: added objects %u, released objects %u\n", m_Added, m_Released));
185
186 /* Try to delete m_CritSectData */
187 RTCritSectDelete(&m_CritSectData);
188 }
189}
190
191bool TrackedObjectsCollector::init(){
192 m_fInitialized = false;
193
194 /* Create the critical section protecting the m_trackedObjectsData */
195 int vrc = RTCritSectInit(&m_CritSectData);
196
197 if (RT_SUCCESS(vrc))
198 {
199 /*
200 * TrackedObjectsCollector initialization occurs only when new instance of VirtualBox is created.
201 * At this moment nobody uses the TrackedObjectsCollector and we can call the functions without any locking.
202 */
203 vrc = i_clear();//just in case
204 if (RT_SUCCESS(vrc))
205 {
206 m_fInitialized = true;
207 LogRel(("The collector has been initialized.\n"));
208 }
209 }
210
211 return m_fInitialized;
212}
213
214bool TrackedObjectsCollector::uninit()
215{
216 clear(Uninitialization);
217
218
219 /* Deletion the critical section protecting the m_trackedObjectsData */
220 int vrc = RTCritSectDelete(&m_CritSectData);
221
222 if (RT_SUCCESS(vrc))
223 m_fInitialized = false;
224
225 return m_fInitialized;
226}
227
228int TrackedObjectsCollector::i_checkInitialization() const
229{
230 int vrc = VINF_SUCCESS;
231 if (!m_fInitialized)
232 {
233 Log2(("The collector is in the uninitialized state...\n"));
234 vrc = VERR_INVALID_STATE;
235 }
236
237 return vrc;
238}
239
240HRESULT TrackedObjectsCollector::setObj (const com::Utf8Str &aObjId,
241 const com::Utf8Str &aClassIID,
242 uint64_t lifeTime,
243 uint64_t idleTime,
244 IUnknown* ptrIface)
245{
246 LogFlowFuncEnter();
247
248 HRESULT hrc = S_OK;
249 int vrc = i_checkInitialization();
250 if (RT_FAILURE(vrc))
251 return VBOX_E_INVALID_OBJECT_STATE;
252
253 /* Enter critical section here */
254 RTCritSectEnter(&m_CritSectData);
255
256 com::Guid idObj(aObjId);
257 com::Guid classIID(aClassIID);
258 std::pair < std::set<com::Utf8Str>::iterator, bool > opRes = m_trackedObjectIds.insert(aObjId);
259
260 /*
261 * The case for updating the tracked object data.
262 * The Id is presented in the m_trackedObjectIds. The original object is removed from m_trackedObjectsData.
263 */
264 if (!opRes.second)
265 {
266 Log2(("UPDATING TrackedObjectData: object Id %s, class IID %s, life time %i, idle time %i\n",
267 aObjId.c_str(), aClassIID.c_str(), lifeTime, idleTime));
268
269 m_trackedObjectsData.erase(aObjId.c_str());
270 /* decrease the counter */
271 --m_Added;
272 }
273 else
274 {
275 char szCreationTime[42];
276 RTTIMESPEC time;
277 RTTimeSpecToString(RTTimeNow(&time), szCreationTime, sizeof(szCreationTime));
278 Log2(("ADDED TrackedObjectData: creation time %s, object Id %s, class IID %s\n",
279 szCreationTime, aObjId.c_str(), aClassIID.c_str()));
280 }
281
282 /* Data is stored in the m_trackedObjectsData under the passed Id. */
283 m_trackedObjectsData.insert(std::make_pair(aObjId.c_str(),
284 TrackedObjectData(idObj,
285 classIID,
286 lifeTime,
287 idleTime,
288 ptrIface)));
289
290 /* increase the counter */
291 ++m_Added;
292
293 /* Leave critical section here */
294 RTCritSectLeave(&m_CritSectData);
295
296 return hrc;
297}
298
299HRESULT TrackedObjectsCollector::getObj (const com::Utf8Str& aObjId,
300 TrackedObjectData& aObjData,
301 bool fUpdate)
302{
303 LogFlowFuncEnter();
304
305 int vrc = i_checkInitialization();
306 if (RT_FAILURE(vrc))
307 return VBOX_E_INVALID_OBJECT_STATE;
308
309 /* Enter critical section here */
310 RTCritSectEnter(&m_CritSectData);
311
312 std::string sTemp(aObjId.c_str());
313 HRESULT hrc = E_FAIL;
314
315 iterTrObjDataType pIter = m_trackedObjectsData.find(sTemp);
316 if (pIter != m_trackedObjectsData.end() && fUpdate == true)
317 {
318 /* Update some fields in the found object if needed. in instance, the last access time */
319 com::Utf8Str lat = pIter->second.updateLastAccessTime(); /* Update the access time */
320 Log2(("The updated last access time is %s\n", lat.c_str()));
321 vrc = VINF_SUCCESS;
322 }
323
324 if (RT_SUCCESS(vrc))
325 {
326 if ( i_getObj(aObjId).getInterface().isNotNull() )
327 {
328 /* Excessive check because user may get only the valid objects Ids. But for 200% assurance it's here */
329 if (i_getObj(aObjId).state() == TrackedObjectData::Valid)
330 {
331 aObjData = i_getObj(aObjId);
332 hrc = S_OK;
333 }
334 else
335 hrc = VBOX_E_INVALID_OBJECT_STATE;
336 }
337 else
338 hrc = VBOX_E_OBJECT_NOT_FOUND;
339 }
340
341 /* Leave critical section here */
342 RTCritSectLeave(&m_CritSectData);
343
344 return hrc;
345}
346
347const TrackedObjectData& TrackedObjectsCollector::i_getObj (const com::Utf8Str& aObjId) const
348{
349 /* No check for existence of aObjId */
350 return m_trackedObjectsData.at(aObjId.c_str());
351}
352
353HRESULT TrackedObjectsCollector::initObjIdleTime (const com::Utf8Str& aObjId)
354{
355 LogFlowFuncEnter();
356
357 HRESULT hrc = S_OK;
358 int vrc = i_checkInitialization();
359 if (RT_FAILURE(vrc))
360 return VBOX_E_INVALID_OBJECT_STATE;
361
362 vrc = VERR_NOT_FOUND;
363 /* Enter critical section here */
364 RTCritSectEnter(&m_CritSectData);
365
366 std::string sTemp(aObjId.c_str());
367
368 iterTrObjDataType pIter = m_trackedObjectsData.find(sTemp);
369 if (pIter != m_trackedObjectsData.end())
370 {
371 /* Init idle time only once, next time returns the initialization time */
372 com::Utf8Str strTime = pIter->second.initIdleTime();
373 Log2(("The idle time start is %s\n", strTime.c_str()));
374 vrc = VINF_SUCCESS;
375 }
376
377 if (RT_FAILURE(vrc))
378 hrc = VBOX_E_OBJECT_NOT_FOUND;
379
380 /* Leave critical section here */
381 RTCritSectLeave(&m_CritSectData);
382
383 return hrc;
384}
385
386HRESULT TrackedObjectsCollector::removeObj (const com::Utf8Str& aObjId)
387{
388 Log2(("%s: object Id %s\n", __FUNCTION__, aObjId.c_str()));
389
390 HRESULT hrc = S_OK;
391 int vrc = i_checkInitialization();
392 if (RT_FAILURE(vrc))
393 return VBOX_E_INVALID_OBJECT_STATE;
394
395 std::string sTemp(aObjId.c_str());
396
397 vrc = VERR_NOT_FOUND;
398
399 /* Enter critical section here */
400 RTCritSectEnter(&m_CritSectData);
401
402 cIterTrObjDataType pIter = m_trackedObjectsData.find(sTemp);
403 if (pIter != m_trackedObjectsData.end())
404 {
405 Log2(("RELEASED TrackedObjectData: creation time %s, object Id %s, class IID %s\n",
406 pIter->second.creationTimeStr().c_str(), pIter->second.objectIdStr().c_str(), pIter->second.classIIDStr().c_str()));
407
408 m_trackedObjectsData.erase(pIter);
409 m_trackedObjectIds.erase(aObjId);
410 m_trackedInvalidObjectIds.erase(aObjId);
411
412 /* increase the counter */
413 ++m_Released;
414
415 vrc = VINF_SUCCESS;
416 }
417
418 if (RT_FAILURE(vrc))
419 hrc = VBOX_E_OBJECT_NOT_FOUND;
420
421 /* Leave critical section here */
422 RTCritSectLeave(&m_CritSectData);
423
424 return hrc;
425}
426
427HRESULT TrackedObjectsCollector::getAllObjIds (std::vector<com::Utf8Str>& aObjIdMap)
428{
429 HRESULT hrc = S_OK;
430 int vrc = i_checkInitialization();
431 if (RT_FAILURE(vrc))
432 return VBOX_E_INVALID_OBJECT_STATE;
433
434 /* Enter critical section here */
435 RTCritSectEnter(&m_CritSectData);
436 vrc = i_getAllObjIds(aObjIdMap);
437 if (RT_FAILURE(vrc))
438 hrc = VBOX_E_OBJECT_NOT_FOUND;
439 /* Leave critical section here */
440 RTCritSectLeave(&m_CritSectData);
441
442 return hrc;
443}
444
445int TrackedObjectsCollector::i_getAllObjIds (std::vector<com::Utf8Str>& aObjIdMap) const
446{
447 for (const com::Utf8Str& item : m_trackedObjectIds)
448 {
449 if (!m_trackedInvalidObjectIds.count(item))
450 aObjIdMap.push_back(item);
451 }
452
453 return aObjIdMap.size() > 0 ? VINF_SUCCESS : VERR_NOT_FOUND;
454}
455
456HRESULT TrackedObjectsCollector::getObjIdsByClassIID (const Guid& iid,
457 std::vector<com::Utf8Str>& aObjIdMap)
458{
459 Log2(("%s: Getting all objects Ids with Class IID %s\n", __FUNCTION__, iid.toString().c_str()));
460
461 HRESULT hrc = S_OK;
462 int vrc = i_checkInitialization();
463 if (RT_FAILURE(vrc))
464 return VBOX_E_INVALID_OBJECT_STATE;
465
466 /* Enter critical section here */
467 RTCritSectEnter(&m_CritSectData);
468
469 vrc = i_getObjIdsByClassIID (iid, aObjIdMap);
470 if (RT_FAILURE(vrc))
471 hrc = VBOX_E_OBJECT_NOT_FOUND;
472 /* Leave critical section here */
473 RTCritSectLeave(&m_CritSectData);
474
475 return hrc;
476}
477
478int TrackedObjectsCollector::i_getObjIdsByClassIID (const Guid& iid,
479 std::vector<com::Utf8Str>& aObjIdMap) const
480{
481 for (const std::pair<const std::string, TrackedObjectData>& item : m_trackedObjectsData)
482 {
483 /* IID found and the object is valid */
484 if (item.second.classIID() == iid && !m_trackedInvalidObjectIds.count(item.first.c_str()))
485 aObjIdMap.push_back(item.first.c_str());
486 }
487
488 return aObjIdMap.size() > 0 ? VINF_SUCCESS : VERR_NOT_FOUND;
489}
490
491bool TrackedObjectsCollector::checkObj(const com::Utf8Str& aObjId)
492{
493 Log2(("%s: Checking object with Id %s\n", __FUNCTION__, aObjId.c_str()));
494
495 int vrc = i_checkInitialization();
496 if (RT_FAILURE(vrc))
497 return false;
498
499 RTCritSectEnter(&m_CritSectData);
500 bool res = i_checkObj(aObjId);
501 RTCritSectLeave(&m_CritSectData);
502 return res;
503}
504
505bool TrackedObjectsCollector::i_checkObj(const com::Utf8Str& aObjId) const
506{
507 return m_trackedObjectIds.count(aObjId.c_str()) > 0 ? true : false;
508}
509
510HRESULT TrackedObjectsCollector::clear(TrackedObjectsCollectorState aState)
511{
512 LogFlowFuncEnter();
513
514 HRESULT hrc = S_OK;
515 int vrc = i_checkInitialization();
516 if (RT_FAILURE(vrc))
517 return VBOX_E_INVALID_OBJECT_STATE;
518
519 if (aState != Uninitialization)
520 {
521 /* Enter critical section here */
522 vrc = RTCritSectEnter(&m_CritSectData);
523 if (RT_FAILURE(vrc))
524 {
525 Log2(("%s: Coudn't enter into the critical section (%Rrc)\n", __FUNCTION__, vrc));
526 return E_ABORT;
527 }
528 }
529
530 if (m_trackedObjectsData.size() != 0)
531 {
532 if (m_trackedObjectsData.size() > 1)
533 Log2(("%u objects are still presented in the Objects Collector, clearing...\n", m_trackedObjectsData.size()));
534 else
535 Log2(("%u object is still presented in the Objects Collector, clearing...\n", m_trackedObjectsData.size()));
536
537 vrc = i_clear();
538 /* Ignore setting hrc */
539 if (RT_FAILURE(vrc))
540 LogRel(("Something wrong with clearing the Objects Collector\n"));
541 }
542
543 Log2(("The Objects Collector history data: added objects %u, released objects %u\n", m_Added, m_Released));
544
545 if (aState != Uninitialization)
546 {
547 /* Leave critical section here */
548 RTCritSectLeave(&m_CritSectData);
549 }
550
551 return hrc;
552}
553
554int TrackedObjectsCollector::i_clear()
555{
556 int vrc = VINF_SUCCESS;
557 try
558 {
559 m_Released += m_trackedObjectsData.size();
560 m_trackedObjectsData.clear();
561 m_trackedObjectIds.clear();
562 m_trackedInvalidObjectIds.clear();
563 }
564 catch (...)
565 {
566 vrc = VERR_GENERAL_FAILURE;
567 }
568 return vrc;
569}
570
571HRESULT TrackedObjectsCollector::tryToRemoveObj(const com::Utf8Str& aObjId)
572{
573 LogFlowFuncEnter();
574
575 HRESULT hrc = S_OK;
576 int vrc = i_checkInitialization();
577 if (RT_FAILURE(vrc))
578 return VBOX_E_INVALID_OBJECT_STATE;
579
580 /* Enter critical section here */
581 RTCritSectEnter(&m_CritSectData);
582
583 iterTrObjDataType pIter = m_trackedObjectsData.find(aObjId.c_str());
584 if (pIter != m_trackedObjectsData.end())
585 {
586 pIter->second.getInterface()->AddRef();
587 ULONG cRefs = pIter->second.getInterface()->Release();
588
589 if (cRefs > 1)
590 {
591 Log2(("Object %s with class IID %s can't be released if refcount is more than 1 (now %lu)\n",
592 pIter->second.objectIdStr().c_str(),
593 pIter->second.classIIDStr().c_str(),
594 cRefs
595 ));
596 hrc = E_FAIL;
597 }
598 else
599 {
600 Log2(("Object %s with class IID %s is released (refcount %lu)\n",
601 pIter->second.objectIdStr().c_str(),
602 pIter->second.classIIDStr().c_str(),
603 cRefs
604 ));
605 m_trackedObjectsData.erase(pIter);
606 m_trackedObjectIds.erase(aObjId);
607 m_trackedInvalidObjectIds.erase(aObjId);
608
609 /* increase the counter */
610 ++m_Released;
611 }
612 }
613 else
614 hrc = VBOX_E_OBJECT_NOT_FOUND;
615
616 /* Leave critical section here */
617 RTCritSectLeave(&m_CritSectData);
618
619 return hrc;
620}
621
622/**
623 * Invalidate the tracked object.
624 * Works ONLY in conjunction with setTracked()!
625 */
626HRESULT TrackedObjectsCollector::invalidateObj(const com::Utf8Str &aObjId)
627{
628 LogFlowFuncEnter();
629
630 HRESULT hrc = S_OK;
631 int vrc = i_checkInitialization();
632 if (RT_FAILURE(vrc))
633 return VBOX_E_INVALID_OBJECT_STATE;
634
635 /* Enter critical section here */
636 RTCritSectEnter(&m_CritSectData);
637
638 std::string sTemp(aObjId.c_str());
639 vrc = VERR_NOT_FOUND;
640
641 iterTrObjDataType pIter = m_trackedObjectsData.find(sTemp);
642 if (pIter != m_trackedObjectsData.end())
643 {
644 pIter->second.resetState();
645 m_trackedInvalidObjectIds.insert(aObjId);
646 vrc = VINF_SUCCESS;
647 }
648
649 if (RT_FAILURE(vrc))
650 hrc = VBOX_E_OBJECT_NOT_FOUND;
651
652 /* Leave critical section here */
653 RTCritSectLeave(&m_CritSectData);
654
655 return hrc;
656}
657
658/////////////////////////////////////////////////////////////////////////////
659// ObjectTracker
660/////////////////////////////////////////////////////////////////////////////
661ObjectTracker::~ObjectTracker()
662{
663 LogFlowFuncEnter();
664 LogRel(("Start waiting the ObjectTracker thread termination\n"));
665 RTThreadWait(m_Thread, 30000, NULL);
666 LogRel(("Finished waiting the ObjectTracker thread termination\n"));
667 m_Thread = NIL_RTTHREAD;
668}
669
670bool ObjectTracker::init()
671{
672 LogFlowFuncEnter();
673 return true;
674}
675
676bool ObjectTracker::finish()
677{
678 LogFlowFuncEnter();
679 ASMAtomicWriteBool(&fFinish, true);
680 return fFinish;
681}
682
683bool ObjectTracker::isFinished()
684{
685 LogFlowFuncEnter();
686 ASMAtomicReadBool(&fFinish);
687 return fFinish;
688}
689
690/*static*/
691DECLCALLBACK(int) ObjectTracker::objectTrackerTask(RTTHREAD ThreadSelf, void *pvUser)
692{
693 HRESULT hrc = S_OK;
694
695 NOREF(ThreadSelf);
696 ObjectTracker* const master = (ObjectTracker*)pvUser;
697
698 LogRel(("Starting the ObjectTracker thread %s\n", master->getTaskName().c_str()));
699
700 while (master != NULL && master->isFinished() != true)
701 {
702 std::vector<com::Utf8Str> lObjIdMap;
703
704 hrc = gTrackedObjectsCollector.getAllObjIds(lObjIdMap);
705 for (const com::Utf8Str& item : lObjIdMap)
706 {
707 TrackedObjectData temp;
708 if(gTrackedObjectsCollector.checkObj(item.c_str()))
709 {
710 hrc = gTrackedObjectsCollector.getObj(item.c_str(), temp);
711 if (SUCCEEDED(hrc))
712 {
713 Log2(("Tracked Object with ID %s was found:\n", temp.m_objId.toString().c_str()));
714
715 RTTIMESPEC now;
716 int64_t currTime = RTTimeSpecGetMilli(RTTimeNow(&now));
717 int64_t creationTime = RTTimeSpecGetMilli(&temp.m_creationTime);
718 int64_t lifeTime = (int64_t)temp.m_lifeTime*1000; //convert to milliseconds
719
720 int64_t remainingLifeTime = ((creationTime + lifeTime) - currTime)/1000;
721
722 /* lock? */
723 temp.m_pIface->AddRef();
724 unsigned long cRefs = temp.m_pIface->Release();
725
726 /* cRefs > 2 because we created the temporarily object temp */
727 Log2(("Object %s (class IID %s): refcount %lu, remaining life time is %ld sec\n",
728 temp.m_objId.toString().c_str(),
729 temp.m_classIID.toString().c_str(),
730 cRefs - 1,
731 remainingLifeTime
732 ));
733
734 bool fLifeTimeEnd = (currTime - creationTime) > lifeTime ? true : false;
735
736 if (!fLifeTimeEnd)
737 {
738 if (cRefs <= 2 || remainingLifeTime <= 0)
739 {
740 if (temp.m_fIdleTimeStart == false)
741 {
742 gTrackedObjectsCollector.initObjIdleTime(item);
743 Log2(("Idle time for the object with Id %s has been started\n", item.c_str()));
744 }
745 else
746 {
747 int64_t idleTime = (int64_t)temp.m_idleTime*1000; //convert to milliseconds
748 int64_t idleTimeStart = RTTimeSpecGetMilli(&temp.m_idleTimeStart);
749 bool fObsolete = (currTime - idleTimeStart) > idleTime ? true : false;
750 if (fObsolete)
751 {
752 Log2(("Object with Id %s removed from Object Collector "
753 "(recount is %u, idle time exceeded %u sec)\n", item.c_str(), cRefs - 1, temp.m_idleTime));
754 gTrackedObjectsCollector.removeObj(item.c_str());
755 }
756 }
757 }
758 }
759 else
760 {
761 if (cRefs <= 2)
762 {
763 /*
764 * Special case for the objects with lifeTime == 0.
765 * It's intended for such objects like Mediums or Machines or others.
766 * The objects which live from the beginning but may be deleted by user manually.
767 * for this object the idle time starts when user deletes it.
768 */
769 if (lifeTime == 0)
770 {
771 lifeTime = currTime - creationTime;//in milliseconds
772 /* if lifeTime < 1000 msec (1 sec) set minimal lifeTime to 60 sec (1 min)*/
773 lifeTime = lifeTime < 1000 ? 60 : lifeTime/1000;
774 /* Updating the object data */
775 gTrackedObjectsCollector.setObj(temp.objectIdStr(),
776 temp.classIIDStr(),
777 (uint64_t)lifeTime,
778 temp.m_idleTime,
779 temp.m_pIface);
780 }
781 else
782 {
783 Log2(("Object with Id %s removed from Object Collector "
784 "(lifetime exceeded %u sec)\n", item.c_str(), temp.m_lifeTime));
785 gTrackedObjectsCollector.removeObj(item.c_str());
786 }
787 }
788 }
789 }
790 }
791 else
792 Log2(("Tracked Object with ID %s was not found\n", item.c_str()));
793 }
794
795 //sleep 1 sec
796 RTThreadSleep(RT_MS_1SEC);//1 sec
797 }
798
799 LogRel(("Finishing the object tracker thread %s\n", master->getTaskName().c_str()));
800
801 return 0;
802}
803
804int ObjectTracker::createThread()
805{
806 int vrc = RTThreadCreate(&m_Thread, objectTrackerTask, this, 0,
807 RTTHREADTYPE_INFREQUENT_POLLER,
808 RTTHREADFLAGS_WAITABLE,
809 "ObjTracker");
810
811 return vrc;
812}
813
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette