VirtualBox

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

Last change on this file since 107151 was 107151, checked in by vboxsync, 7 weeks ago

Fixed the case with lifetime equal to 0.

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