VirtualBox

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

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

bugref:10806. New TrackedObjectState enum usage. Added member m_deletionTime. Added the functions updateState, deletionTime. Added getters idleTime, lifeTime, deletionTime, creationTime. Fixed the function resetState and getter state.

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