Fixed occasional deadlock that occurred when dbus connection got
[profile/ivi/common-api-dbus-runtime.git] / src / CommonAPI / DBus / DBusServiceRegistry.h
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 #ifndef COMMONAPI_DBUS_DBUS_SERVICE_REGISTRY_H_
8 #define COMMONAPI_DBUS_DBUS_SERVICE_REGISTRY_H_
9
10 #include <CommonAPI/types.h>
11 #include <CommonAPI/Attribute.h>
12 #include <CommonAPI/Proxy.h>
13
14 #include "DBusProxyConnection.h"
15 #include "DBusAddressTranslator.h"
16 #include "DBusDaemonProxy.h"
17
18 #include <unordered_map>
19 #include <utility>
20 #include <map>
21 #include <unordered_set>
22 #include <string>
23 #include <vector>
24 #include <memory>
25 #include <list>
26 #include <algorithm>
27 #include <set>
28
29 #include <condition_variable>
30 #include <mutex>
31
32 namespace CommonAPI {
33 namespace DBus {
34
35 typedef Event<std::string, std::string, std::string> NameOwnerChangedEvent;
36 typedef Event<std::string, std::string, std::string>::Subscription NameOwnerChangedEventSubscription;
37
38 //connectionName, objectPath
39 typedef std::pair<std::string, std::string> DBusInstanceId;
40
41 class DBusProxyConnection;
42 class DBusDaemonProxy;
43
44
45 class DBusServiceRegistry: public std::enable_shared_from_this<DBusServiceRegistry> {
46  public:
47     enum class DBusServiceState {
48         UNKNOWN,
49         AVAILABLE,
50         RESOLVING,
51         RESOLVED,
52         NOT_AVAILABLE
53     };
54
55     typedef std::function<void(const AvailabilityStatus& availabilityStatus)> DBusServiceListener;
56     typedef std::list<DBusServiceListener> DBusServiceListenerList;
57     typedef DBusServiceListenerList::iterator Subscription;
58
59     typedef std::pair<std::string, std::string> DBusObjectInterfacePair;
60     typedef std::unordered_map<DBusObjectInterfacePair, std::pair<AvailabilityStatus, DBusServiceListenerList> > DBusInstanceList;
61     typedef std::unordered_map<std::string, std::pair<DBusServiceState, DBusInstanceList> > DBusServiceList;
62
63
64     DBusServiceRegistry(std::shared_ptr<DBusProxyConnection> dbusProxyConnection);
65
66     virtual ~DBusServiceRegistry();
67
68     void init();
69
70     bool isServiceInstanceAlive(const std::string& dbusInterfaceName, const std::string& dbusConnectionName, const std::string& dbusObjectPath);
71
72     Subscription subscribeAvailabilityListener(const std::string& commonApiAddress,
73                                                DBusServiceListener serviceListener);
74     void unsubscribeAvailabilityListener(const std::string& commonApiAddress,
75                                          Subscription& listenerSubscription);
76
77     virtual std::vector<std::string> getAvailableServiceInstances(const std::string& interfaceName,
78                                                                   const std::string& domainName = "local");
79
80  private:
81     DBusServiceRegistry(const DBusServiceRegistry&) = delete;
82     DBusServiceRegistry& operator=(const DBusServiceRegistry&) = delete;
83
84     SubscriptionStatus onDBusDaemonProxyStatusEvent(const AvailabilityStatus& availabilityStatus);
85     SubscriptionStatus onDBusDaemonProxyNameOwnerChangedEvent(const std::string& name, const std::string& oldOwner, const std::string& newOwner);
86
87     void onListNamesCallback(const CommonAPI::CallStatus& callStatus, std::vector<std::string> dbusNames);
88
89     void resolveDBusServiceInstances(DBusServiceList::iterator& dbusServiceIterator);
90     void onGetManagedObjectsCallback(const CallStatus& status, DBusDaemonProxy::DBusObjectToInterfaceDict managedObjects, const std::string& dbusServiceName);
91
92     size_t getAvailableServiceInstances(const std::string& dbusInterfaceName, std::vector<std::string>& availableServiceInstances);
93
94     bool waitDBusServicesAvailable(std::unique_lock<std::mutex>& lock, std::chrono::milliseconds& timeout);
95
96     void onDBusServiceAvailabilityStatus(const std::string& dbusServiceName, const AvailabilityStatus& availabilityStatus);
97     DBusServiceList::iterator onDBusServiceAvailabilityStatus(DBusServiceList::iterator& dbusServiceIterator, const AvailabilityStatus& availabilityStatus);
98     DBusServiceList::iterator onDBusServiceOffline(DBusServiceList::iterator& dbusServiceIterator, const DBusServiceState& dbusServiceState);
99
100     static void onDBusServiceInstanceAvailable(
101                     DBusInstanceList& dbusInstanceList,
102                     const std::string& dbusObjectPath,
103                     const std::string& dbusInterfaceName);
104
105     static DBusInstanceList::iterator addDBusServiceInstance(
106                     DBusInstanceList& dbusInstanceList,
107                     const std::string& dbusObjectPath,
108                     const std::string& dbusInterfaceName);
109
110     static void notifyDBusServiceListeners(DBusServiceListenerList& dbusServiceListenerList, const AvailabilityStatus& availabilityStatus);
111
112     static bool isDBusServiceName(const std::string& name);
113
114
115     std::shared_ptr<DBusDaemonProxy> dbusDaemonProxy_;
116
117     DBusServiceList dbusServices_;
118     AvailabilityStatus dbusServicesStatus_;
119     std::condition_variable dbusServiceChanged_;
120
121     std::mutex dbusServicesMutex_;
122
123     ProxyStatusEvent::Subscription dbusDaemonProxyStatusEventSubscription_;
124     NameOwnerChangedEvent::Subscription dbusDaemonProxyNameOwnerChangedEventSubscription_;
125 };
126
127 } // namespace DBus
128 } // namespace CommonAPI
129
130 #endif // COMMONAPI_DBUS_DBUS_SERVICE_REGISTRY_H_