Fixed occasional deadlock that occurred when dbus connection got
[profile/ivi/common-api-dbus-runtime.git] / src / CommonAPI / DBus / DBusServiceRegistry.cpp
1 /* Copyright (C) 2013 BMW Group
2  * Author: Manfred Bathelt (manfred.bathelt@bmw.de)
3  * Author: Juergen Gehring (juergen.gehring@bmw.de)
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "DBusFunctionalHash.h"
8 #include "DBusServiceRegistry.h"
9 #include "DBusDaemonProxy.h"
10 #include "DBusProxyAsyncCallbackHandler.h"
11
12 namespace CommonAPI {
13 namespace DBus {
14
15
16 DBusServiceRegistry::DBusServiceRegistry(std::shared_ptr<DBusProxyConnection> dbusProxyConnection):
17                 dbusDaemonProxy_(std::make_shared<CommonAPI::DBus::DBusDaemonProxy>(dbusProxyConnection)),
18                 dbusServicesStatus_(AvailabilityStatus::UNKNOWN) {
19 }
20
21 DBusServiceRegistry::~DBusServiceRegistry() {
22     dbusDaemonProxy_->getNameOwnerChangedEvent().unsubscribe(dbusDaemonProxyNameOwnerChangedEventSubscription_);
23     dbusDaemonProxy_->getProxyStatusEvent().unsubscribe(dbusDaemonProxyStatusEventSubscription_);
24     std::cout << "Crushing stuff" << std::endl;
25 }
26
27 void DBusServiceRegistry::init() {
28     dbusDaemonProxyStatusEventSubscription_ =
29                     dbusDaemonProxy_->getProxyStatusEvent().subscribeCancellableListener(
30                                     std::bind(&DBusServiceRegistry::onDBusDaemonProxyStatusEvent, this->shared_from_this(), std::placeholders::_1));
31
32     dbusDaemonProxyNameOwnerChangedEventSubscription_ =
33                     dbusDaemonProxy_->getNameOwnerChangedEvent().subscribeCancellableListener(
34                     std::bind(&DBusServiceRegistry::onDBusDaemonProxyNameOwnerChangedEvent,
35                               this->shared_from_this(),
36                               std::placeholders::_1,
37                               std::placeholders::_2,
38                               std::placeholders::_3));
39 }
40
41 bool DBusServiceRegistry::waitDBusServicesAvailable(std::unique_lock<std::mutex>& lock, std::chrono::milliseconds& timeout) {
42     bool dbusServicesStatusIsKnown = (dbusServicesStatus_ != AvailabilityStatus::UNKNOWN);
43
44     while (!dbusServicesStatusIsKnown && timeout.count() > 0) {
45         typedef std::chrono::high_resolution_clock clock;
46         clock::time_point startTimePoint = clock::now();
47
48         dbusServicesStatusIsKnown = dbusServiceChanged_.wait_for(
49                                         lock,
50                                         timeout,
51                                         [&]{ return dbusServicesStatus_ != AvailabilityStatus::UNKNOWN; });
52
53         std::chrono::milliseconds elapsedWaitTime =
54                                     std::chrono::duration_cast<std::chrono::milliseconds>(clock::now() - startTimePoint);
55
56         if (elapsedWaitTime > timeout) {
57             timeout = std::chrono::milliseconds::zero();
58             break;
59         }
60
61         timeout -= elapsedWaitTime;
62     }
63
64     return (dbusServicesStatus_ == AvailabilityStatus::AVAILABLE);
65 }
66
67 bool DBusServiceRegistry::isServiceInstanceAlive(const std::string& dbusInterfaceName, const std::string& dbusServiceName, const std::string& dbusObjectPath) {
68     if (!dbusDaemonProxy_->isAvailable()) {
69         return false;
70     }
71
72     std::chrono::milliseconds timeout(2000);
73     std::unique_lock<std::mutex> dbusServicesLock(dbusServicesMutex_);
74
75     if (!waitDBusServicesAvailable(dbusServicesLock, timeout)) {
76         return false;
77     }
78
79     auto dbusServiceIterator = dbusServices_.find(dbusServiceName);
80     if (dbusServiceIterator == dbusServices_.end()) {
81         return false;
82     }
83
84     DBusServiceState& dbusServiceState = dbusServiceIterator->second.first;
85
86     if (dbusServiceState == DBusServiceState::AVAILABLE) {
87         resolveDBusServiceInstances(dbusServiceIterator);
88     }
89
90     if (dbusServiceState == DBusServiceState::RESOLVING) {
91         dbusServiceChanged_.wait_for(
92                         dbusServicesLock,
93                         timeout,
94                         [&] { return dbusServiceState != DBusServiceState::RESOLVING; });
95     }
96
97     const DBusInstanceList& dbusInstanceList = dbusServiceIterator->second.second;
98     auto dbusInstanceIterator = dbusInstanceList.find({ dbusObjectPath, dbusInterfaceName });
99
100     if (dbusInstanceIterator != dbusInstanceList.end()) {
101         const AvailabilityStatus& dbusInstanceAvailabilityStatus = dbusInstanceIterator->second.first;
102
103         return (dbusInstanceAvailabilityStatus == AvailabilityStatus::AVAILABLE);
104     }
105
106     return false;
107 }
108
109 // Go through the list of available services and check their interface lists
110 // If a list is still unknown, then send request to the remote object manager and count it as invalid
111 // If a list is in acquiring state, then just count it as invalid and skip over it
112 // Add all matching valid services to the available service list
113 // If the invalid service count is set, then wait upto waitTimeLimit (2 seconds) for the object manager requests to complete
114 // If the timeout expires, then go through the list for last time and add everything matching
115 // If the timeout didn't expire, then go through the list again and send requests for new UNKNOWN services, then wait again for them to complete
116 // Known limitations:
117 //   - if the method is called before the first "listNames()" call completes, this request will be blocked
118 //   - if libdbus is broken and doesn't report errors to timed out requests, then this request will always block for the default 2 seconds (waitTimeLimit)
119 //   - the method has to be called many times, if you actually want to wait for all services, otherwise you'll always get a partial response. I.e. the more you call this method, the hotter the internal cache gets.
120 std::vector<std::string> DBusServiceRegistry::getAvailableServiceInstances(const std::string& serviceName,
121                                                                            const std::string& domainName) {
122     std::vector<std::string> availableServiceInstances;
123
124     if (!dbusDaemonProxy_->isAvailable()) {
125         return availableServiceInstances;
126     }
127
128     std::chrono::milliseconds timeout(2000);
129     std::unique_lock<std::mutex> dbusServicesLock(dbusServicesMutex_);
130
131     if (!waitDBusServicesAvailable(dbusServicesLock, timeout)) {
132         return availableServiceInstances;
133     }
134
135     while (timeout.count() > 0) {
136         size_t dbusServiceResolvingCount = getAvailableServiceInstances(serviceName, availableServiceInstances);
137
138         if (!dbusServiceResolvingCount) {
139             break;
140         }
141
142         // wait for unknown and acquiring services, then restart from the beginning
143         typedef std::chrono::high_resolution_clock clock;
144         clock::time_point startTimePoint = clock::now();
145
146         size_t wakeupCount = 0;
147         dbusServiceChanged_.wait_for(
148                         dbusServicesLock,
149                         timeout,
150                         [&] {
151                             wakeupCount++;
152                             return wakeupCount > dbusServiceResolvingCount;
153                         });
154
155         if (wakeupCount > 1) {
156             getAvailableServiceInstances(serviceName, availableServiceInstances);
157             break;
158         }
159
160         std::chrono::milliseconds elapsedWaitTime =
161                         std::chrono::duration_cast<std::chrono::milliseconds>(clock::now() - startTimePoint);
162         timeout -= elapsedWaitTime;
163     }
164
165     // maybe partial list but it contains everything we know for now
166     return availableServiceInstances;
167 }
168
169 size_t DBusServiceRegistry::getAvailableServiceInstances(const std::string& dbusInterfaceName, std::vector<std::string>& availableServiceInstances) {
170     size_t dbusServicesResolvingCount = 0;
171
172     availableServiceInstances.clear();
173
174     // caller must hold lock
175     auto dbusServiceIterator = dbusServices_.begin();
176     while (dbusServiceIterator != dbusServices_.end()) {
177         const std::string& dbusServiceName = dbusServiceIterator->first;
178         DBusServiceState& dbusServiceState = dbusServiceIterator->second.first;
179         const DBusInstanceList& dbusInstanceList = dbusServiceIterator->second.second;
180
181         // count the resolving services and start aclquiring the objects for unknown ones
182         switch (dbusServiceState) {
183             case DBusServiceState::AVAILABLE:
184                 resolveDBusServiceInstances(dbusServiceIterator);
185                 dbusServicesResolvingCount++;
186                 break;
187
188             case DBusServiceState::RESOLVING:
189             case DBusServiceState::RESOLVED:
190                 if (dbusServiceState == DBusServiceState::RESOLVING) {
191                     dbusServicesResolvingCount++;
192                 }
193
194                 for (auto& dbusInstanceIterator : dbusInstanceList) {
195                     const AvailabilityStatus& dbusInstanceAvailabilityStatus = dbusInstanceIterator.second.first;
196                     const std::string& dbusInstanceObjectPath = dbusInstanceIterator.first.first;
197                     const std::string& dbusInstanceInterfaceName = dbusInstanceIterator.first.second;
198
199                     if (dbusInstanceAvailabilityStatus == AvailabilityStatus::AVAILABLE
200                                     && dbusInstanceInterfaceName == dbusInterfaceName) {
201                         std::string commonApiAddress;
202
203                         DBusAddressTranslator::getInstance().searchForCommonAddress(
204                                         dbusInterfaceName,
205                                         dbusServiceName,
206                                         dbusInstanceObjectPath,
207                                         commonApiAddress);
208
209                         availableServiceInstances.emplace_back(std::move(commonApiAddress));
210                     }
211                 }
212                 break;
213         }
214
215         dbusServiceIterator++;
216     }
217
218     return dbusServicesResolvingCount;
219 }
220
221
222 DBusServiceRegistry::Subscription DBusServiceRegistry::subscribeAvailabilityListener(const std::string& commonApiAddress,
223                                                                                      DBusServiceListener serviceListener) {
224     std::string dbusInterfaceName;
225     std::string dbusServiceName;
226     std::string dbusObjectPath;
227
228     DBusAddressTranslator::getInstance().searchForDBusAddress(commonApiAddress, dbusInterfaceName, dbusServiceName, dbusObjectPath);
229
230     std::lock_guard<std::mutex> dbusServicesLock(dbusServicesMutex_);
231
232     auto dbusServiceIterator = dbusServices_.find(dbusServiceName);
233
234     // add service for the first time
235     if (dbusServiceIterator == dbusServices_.end()) {
236         DBusServiceState dbusServiceState = DBusServiceState::UNKNOWN;
237
238         if (dbusServicesStatus_ == AvailabilityStatus::AVAILABLE) {
239             dbusServiceState = DBusServiceState::NOT_AVAILABLE;
240         }
241
242         auto insertIterator = dbusServices_.insert({ dbusServiceName, { dbusServiceState, DBusInstanceList() } });
243         assert(insertIterator.second);
244         dbusServiceIterator = insertIterator.first;
245     }
246
247     DBusServiceState& dbusServiceState = dbusServiceIterator->second.first;
248     DBusInstanceList& dbusInstanceList = dbusServiceIterator->second.second;
249
250     auto dbusInstanceIterator = addDBusServiceInstance(
251                     dbusInstanceList,
252                     dbusObjectPath,
253                     dbusInterfaceName);
254     AvailabilityStatus& dbusInstanceAvailabilityStatus = dbusInstanceIterator->second.first;
255     DBusServiceListenerList& dbusServiceListenerList = dbusInstanceIterator->second.second;
256
257     if (dbusServiceState == DBusServiceState::RESOLVED
258                     && dbusInstanceAvailabilityStatus == AvailabilityStatus::UNKNOWN) {
259         dbusInstanceAvailabilityStatus = AvailabilityStatus::NOT_AVAILABLE;
260     }
261
262     Subscription listenerSubscription = dbusServiceListenerList.insert(
263                     dbusServiceListenerList.end(), serviceListener);
264
265     switch (dbusServiceState) {
266         case DBusServiceState::AVAILABLE:
267             resolveDBusServiceInstances(dbusServiceIterator);
268             break;
269
270         case DBusServiceState::RESOLVING:
271             if (dbusInstanceAvailabilityStatus == AvailabilityStatus::AVAILABLE) {
272                 serviceListener(dbusInstanceAvailabilityStatus);
273             }
274             break;
275
276         case DBusServiceState::RESOLVED:
277         case DBusServiceState::NOT_AVAILABLE:
278             serviceListener(dbusInstanceAvailabilityStatus);
279             break;
280     }
281
282     return listenerSubscription;
283 }
284
285 void DBusServiceRegistry::unsubscribeAvailabilityListener(const std::string& commonApiAddress,
286                                                           Subscription& listenerSubscription) {
287     std::string dbusInterfaceName;
288     std::string dbusServiceName;
289     std::string dbusObjectPath;
290
291     DBusAddressTranslator::getInstance().searchForDBusAddress(commonApiAddress, dbusInterfaceName, dbusServiceName, dbusObjectPath);
292
293     std::lock_guard<std::mutex> dbusServicesLock(dbusServicesMutex_);
294     auto dbusServiceIterator = dbusServices_.find(dbusServiceName);
295
296     if (dbusServiceIterator == dbusServices_.end()) {
297         return;
298     }
299
300     DBusServiceState& dbusServiceState = dbusServiceIterator->second.first;
301     DBusInstanceList& dbusInstanceList = dbusServiceIterator->second.second;
302
303     auto dbusInstanceIterator = dbusInstanceList.find({ dbusObjectPath, dbusInterfaceName });
304     if (dbusInstanceIterator == dbusInstanceList.end()) {
305         return;
306     }
307
308     const AvailabilityStatus& dbusServiceAvailabilityStatus = dbusInstanceIterator->second.first;
309     DBusServiceListenerList& dbusServiceListenerList = dbusInstanceIterator->second.second;
310
311     dbusServiceListenerList.erase(listenerSubscription);
312
313     if (dbusServiceListenerList.empty() && dbusServiceAvailabilityStatus != AvailabilityStatus::AVAILABLE) {
314         dbusInstanceList.erase(dbusInstanceIterator);
315
316         if (dbusInstanceList.empty() && dbusServiceState == DBusServiceState::UNKNOWN) {
317             dbusServices_.erase(dbusServiceIterator);
318         }
319     }
320 }
321
322 SubscriptionStatus DBusServiceRegistry::onDBusDaemonProxyStatusEvent(const AvailabilityStatus& availabilityStatus) {
323     std::unique_lock<std::mutex> dbusServicesLock(dbusServicesMutex_);
324
325     switch (availabilityStatus) {
326         case AvailabilityStatus::AVAILABLE:
327             dbusServicesStatus_ = AvailabilityStatus::UNKNOWN;
328             dbusDaemonProxy_->listNamesAsync(std::bind(
329                             &DBusServiceRegistry::onListNamesCallback,
330                             this->shared_from_this(),
331                             std::placeholders::_1,
332                             std::placeholders::_2));
333             break;
334
335         case AvailabilityStatus::NOT_AVAILABLE:
336             auto dbusServiceIterator = dbusServices_.begin();
337
338             while (dbusServiceIterator != dbusServices_.end()) {
339                 dbusServiceIterator = onDBusServiceOffline(dbusServiceIterator, DBusServiceState::NOT_AVAILABLE);
340             }
341
342             dbusServicesStatus_ = AvailabilityStatus::NOT_AVAILABLE;
343             break;
344     }
345
346     return SubscriptionStatus::RETAIN;
347 }
348
349 SubscriptionStatus DBusServiceRegistry::onDBusDaemonProxyNameOwnerChangedEvent(const std::string& affectedName,
350                                                                                const std::string& oldOwner,
351                                                                                const std::string& newOwner) {
352     if (isDBusServiceName(affectedName)) {
353         AvailabilityStatus dbusServiceAvailabilityStatus = AvailabilityStatus::AVAILABLE;
354
355         if (newOwner.empty()) {
356             dbusServiceAvailabilityStatus = AvailabilityStatus::NOT_AVAILABLE;
357         }
358
359         std::unique_lock<std::mutex> dbusServicesLock(dbusServicesMutex_);
360
361         onDBusServiceAvailabilityStatus(affectedName, dbusServiceAvailabilityStatus);
362     }
363
364     return SubscriptionStatus::RETAIN;
365 }
366
367 void DBusServiceRegistry::onListNamesCallback(const CommonAPI::CallStatus& callStatus, std::vector<std::string> dbusNames) {
368     std::unique_lock<std::mutex> dbusServicesLock(dbusServicesMutex_);
369
370     if (callStatus == CallStatus::SUCCESS) {
371         for (const std::string& dbusName : dbusNames) {
372             if (isDBusServiceName(dbusName)) {
373                 onDBusServiceAvailabilityStatus(dbusName, AvailabilityStatus::AVAILABLE);
374             }
375         }
376     }
377
378     dbusServicesStatus_ = AvailabilityStatus::AVAILABLE;
379
380     auto dbusServiceIterator = dbusServices_.begin();
381     while (dbusServiceIterator != dbusServices_.end()) {
382         const DBusServiceState& dbusServiceState = dbusServiceIterator->second.first;
383
384         if (dbusServiceState == DBusServiceState::UNKNOWN) {
385             dbusServiceIterator = onDBusServiceOffline(dbusServiceIterator, DBusServiceState::NOT_AVAILABLE);
386         } else {
387             dbusServiceIterator++;
388         }
389     }
390 }
391
392 void DBusServiceRegistry::onDBusServiceAvailabilityStatus(const std::string& dbusServiceName, const AvailabilityStatus& availabilityStatus) {
393     auto dbusServiceIterator = dbusServices_.find(dbusServiceName);
394
395     if (dbusServiceIterator != dbusServices_.end()) {
396         onDBusServiceAvailabilityStatus(dbusServiceIterator, availabilityStatus);
397
398     } else if (availabilityStatus == AvailabilityStatus::AVAILABLE) {
399         dbusServices_.insert({ dbusServiceName, { DBusServiceState::AVAILABLE, DBusInstanceList() } });
400         dbusServiceChanged_.notify_all();
401     }
402 }
403
404 DBusServiceRegistry::DBusServiceList::iterator DBusServiceRegistry::onDBusServiceAvailabilityStatus(DBusServiceList::iterator& dbusServiceIterator,
405                                                                                                     const AvailabilityStatus& availabilityStatus) {
406     DBusServiceState& dbusServiceState = dbusServiceIterator->second.first;
407     DBusInstanceList& dbusInstanceList = dbusServiceIterator->second.second;
408
409     if (availabilityStatus == AvailabilityStatus::AVAILABLE) {
410         const std::string& dbusServiceName = dbusServiceIterator->first;
411
412         if (dbusServiceState != DBusServiceState::RESOLVING) {
413             resolveDBusServiceInstances(dbusServiceIterator);
414         }
415
416         return dbusServiceIterator;
417     }
418
419     dbusServiceState = (availabilityStatus == AvailabilityStatus::UNKNOWN) ?
420                     DBusServiceState::UNKNOWN :
421                     DBusServiceState::NOT_AVAILABLE;
422
423     return onDBusServiceOffline(dbusServiceIterator, dbusServiceState);
424 }
425
426 DBusServiceRegistry::DBusServiceList::iterator DBusServiceRegistry::onDBusServiceOffline(DBusServiceList::iterator& dbusServiceIterator,
427                                                                                          const DBusServiceState& newDBusServiceState) {
428     DBusServiceState& dbusServiceState = dbusServiceIterator->second.first;
429     DBusInstanceList& dbusInstanceList = dbusServiceIterator->second.second;
430     auto dbusInstanceIterator = dbusInstanceList.begin();
431
432     assert(newDBusServiceState == DBusServiceState::UNKNOWN || newDBusServiceState == DBusServiceState::NOT_AVAILABLE);
433
434     dbusServiceState = newDBusServiceState;
435
436     while (dbusInstanceIterator != dbusInstanceList.end()) {
437         AvailabilityStatus& dbusInstanceAvailabilityStatus = dbusInstanceIterator->second.first;
438         DBusServiceListenerList& dbusServiceListenerList = dbusInstanceIterator->second.second;
439
440         // notify listeners
441         if (!dbusServiceListenerList.empty()) {
442             // the internal state is unknown until the next time we ask the object manager
443             notifyDBusServiceListeners(dbusServiceListenerList, AvailabilityStatus::NOT_AVAILABLE);
444             dbusInstanceAvailabilityStatus = AvailabilityStatus::UNKNOWN;
445             dbusInstanceIterator++;
446         } else {
447             dbusInstanceIterator = dbusInstanceList.erase(dbusInstanceIterator);
448         }
449     }
450
451     dbusServiceChanged_.notify_all();
452
453     if (dbusInstanceList.empty()) {
454         return dbusServices_.erase(dbusServiceIterator);
455     }
456
457     dbusServiceIterator++;
458
459     return dbusServiceIterator;
460 }
461
462 void DBusServiceRegistry::resolveDBusServiceInstances(DBusServiceList::iterator& dbusServiceIterator) {
463     const std::string& dbusServiceName = dbusServiceIterator->first;
464     DBusServiceState& dbusServiceState = dbusServiceIterator->second.first;
465     DBusInstanceList& dbusInstanceList = dbusServiceIterator->second.second;
466     std::vector<DBusServiceAddress> predefinedDBusServiceInstances;
467
468     dbusServiceState = DBusServiceState::RESOLVING;
469
470     // add predefined instances
471     DBusAddressTranslator::getInstance().getPredefinedInstances(dbusServiceName, predefinedDBusServiceInstances);
472
473     for (auto& dbusServiceAddress : predefinedDBusServiceInstances) {
474         const std::string& dbusObjectPath = std::get<1>(dbusServiceAddress);
475         const std::string& dbusInterfaceName = std::get<2>(dbusServiceAddress);
476
477         onDBusServiceInstanceAvailable(dbusInstanceList, dbusObjectPath, dbusInterfaceName);
478     }
479
480     dbusServiceChanged_.notify_all();
481
482     // search for remote instances
483     DBusDaemonProxy::GetManagedObjectsAsyncCallback callback = std::bind(&DBusServiceRegistry::onGetManagedObjectsCallback,
484                                                                          this->shared_from_this(),
485                                                                          std::placeholders::_1,
486                                                                          std::placeholders::_2,
487                                                                          dbusServiceName);
488     dbusDaemonProxy_->getManagedObjectsAsync(dbusServiceName, callback);
489 }
490
491 void DBusServiceRegistry::onGetManagedObjectsCallback(const CallStatus& callStatus,
492                                                       DBusDaemonProxy::DBusObjectToInterfaceDict managedObjects,
493                                                       const std::string& dbusServiceName) {
494     std::unique_lock<std::mutex> dbusServicesLock(dbusServicesMutex_);
495
496     // already offline
497     if (dbusServicesStatus_ == AvailabilityStatus::NOT_AVAILABLE) {
498         return;
499     }
500
501     auto dbusServiceIterator = dbusServices_.find(dbusServiceName);
502     if (dbusServiceIterator == dbusServices_.end()) {
503         return; // nothing we can do
504     }
505
506     DBusServiceState& dbusServiceState = dbusServiceIterator->second.first;
507     DBusInstanceList& dbusInstanceList = dbusServiceIterator->second.second;
508
509     dbusServiceState = DBusServiceState::RESOLVED;
510
511     if (callStatus == CallStatus::SUCCESS) {
512         for (auto& dbusObjectPathIterator : managedObjects) {
513             const std::string& dbusObjectPath = dbusObjectPathIterator.first;
514
515             for (auto& dbusInterfaceNameIterator : dbusObjectPathIterator.second) {
516                 const std::string& dbusInterfaceName = dbusInterfaceNameIterator.first;
517
518                 onDBusServiceInstanceAvailable(dbusInstanceList, dbusObjectPath, dbusInterfaceName);
519             }
520         }
521     }
522
523     dbusServiceChanged_.notify_all();
524
525     // notify only UNKNOWN. The predefined and resolved have already been handled
526     for (auto& dbusInstanceIterator : dbusInstanceList) {
527         AvailabilityStatus& dbusInstanceAvailabilityStatus = dbusInstanceIterator.second.first;
528         DBusServiceListenerList& dbusServiceListenerList = dbusInstanceIterator.second.second;
529
530         if (dbusInstanceAvailabilityStatus == AvailabilityStatus::UNKNOWN) {
531             dbusInstanceAvailabilityStatus = AvailabilityStatus::NOT_AVAILABLE;
532             notifyDBusServiceListeners(dbusServiceListenerList, dbusInstanceAvailabilityStatus);
533         }
534     }
535 }
536
537 void DBusServiceRegistry::onDBusServiceInstanceAvailable(DBusInstanceList& dbusInstanceList,
538                                                          const std::string& dbusObjectPath,
539                                                          const std::string& dbusInterfaceName) {
540     auto dbusInstanceIterator = addDBusServiceInstance(dbusInstanceList, dbusObjectPath, dbusInterfaceName);
541     AvailabilityStatus& dbusInstanceAvailabilityStatus = dbusInstanceIterator->second.first;
542     DBusServiceListenerList& dbusServiceListenerList = dbusInstanceIterator->second.second;
543
544     dbusInstanceAvailabilityStatus = AvailabilityStatus::AVAILABLE;
545
546     notifyDBusServiceListeners(dbusServiceListenerList, dbusInstanceAvailabilityStatus);
547 }
548
549 DBusServiceRegistry::DBusInstanceList::iterator DBusServiceRegistry::addDBusServiceInstance(DBusInstanceList& dbusInstanceList,
550                                                                                             const std::string& dbusObjectPath,
551                                                                                             const std::string& dbusInterfaceName) {
552     auto dbusInstanceIterator = dbusInstanceList.find({ dbusObjectPath, dbusInterfaceName });
553
554     // add instance for the first time
555     if (dbusInstanceIterator == dbusInstanceList.end()) {
556        auto insertIterator = dbusInstanceList.insert(
557                         { { dbusObjectPath, dbusInterfaceName }, { AvailabilityStatus::UNKNOWN, DBusServiceListenerList() } });
558        const bool& insertSuccessfull = insertIterator.second;
559
560        assert(insertSuccessfull);
561        dbusInstanceIterator = insertIterator.first;
562     }
563
564     return dbusInstanceIterator;
565 }
566
567 void DBusServiceRegistry::notifyDBusServiceListeners(DBusServiceListenerList& dbusServiceListenerList,
568                                                      const AvailabilityStatus& availabilityStatus) {
569     for (auto& dbusServiceListener : dbusServiceListenerList) {
570         dbusServiceListener(availabilityStatus);
571     }
572 }
573
574 bool DBusServiceRegistry::isDBusServiceName(const std::string& name) {
575     return name[0] != ':';
576 }
577
578 }// namespace DBus
579 }// namespace CommonAPI