Store the dbus connection while launching the service
[platform/core/context/context-service.git] / src / agent / legacy / trigger / ContextMonitor.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <Types.h>
18 #include "../access_control/Privilege.h"
19 #include "../ContextManager.h"
20 #include "ContextMonitor.h"
21 #include "IContextListener.h"
22 #include "FactRequest.h"
23
24 using namespace ctx;
25 using namespace trigger;
26
27 static int __lastRid;
28 static int __lastErr;
29
30 ContextMonitor *ContextMonitor::__instance = NULL;
31 ContextManager *ContextMonitor::__contextMgr = NULL;
32
33 static int __generateReqId()
34 {
35         static int reqId = 0;
36
37         if (++reqId < 0) {
38                 // Overflow handling
39                 reqId = 1;
40         }
41
42         return reqId;
43 }
44
45 ContextMonitor::ContextMonitor()
46 {
47 }
48
49 ContextMonitor::~ContextMonitor()
50 {
51 }
52
53 void ContextMonitor::setContextManager(ContextManager* ctxMgr)
54 {
55         __contextMgr = ctxMgr;
56 }
57
58 ContextMonitor* ContextMonitor::getInstance()
59 {
60         IF_FAIL_RETURN_TAG(__contextMgr, NULL, _E, "Context manager is needed");
61
62         IF_FAIL_RETURN(!__instance, __instance);
63
64         __instance = new(std::nothrow) ContextMonitor();
65         IF_FAIL_RETURN_TAG(__instance, NULL, _E, "Memory alllocation failed");
66
67         return __instance;
68 }
69
70 void ContextMonitor::destroy()
71 {
72         if (__instance) {
73                 delete __instance;
74                 __instance = NULL;
75         }
76 }
77
78 int ContextMonitor::subscribe(int ruleId, std::string subject, CtxJson1 option, IContextListener* listener)
79 {
80         int reqId = __subscribe(subject.c_str(), &option, listener);
81         IF_FAIL_RETURN_TAG(reqId > 0, reqId, _E, "Subscribe event failed");
82         _D(YELLOW("Subscribe event(rule%d). req%d"), ruleId, reqId);
83
84         return ERR_NONE;
85 }
86
87 int ContextMonitor::__subscribe(const char* subject, CtxJson1* option, IContextListener* listener)
88 {
89         IF_FAIL_RETURN(subject, ERR_INVALID_PARAMETER);
90
91         int rid = __findSub(REQ_SUBSCRIBE, subject, option);
92         if (rid > 0) {
93                 __addListener(REQ_SUBSCRIBE, rid, listener);
94                 _D("Duplicated request for %s", subject);
95                 return rid;
96         }
97
98         rid = __generateReqId();
99
100         FactRequest *req = new(std::nothrow) FactRequest(REQ_SUBSCRIBE,
101                         rid, subject, option ? option->str().c_str() : NULL, this);
102         IF_FAIL_RETURN_TAG(req, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed");
103
104         __contextMgr->assignRequest(req);
105         __addSub(REQ_SUBSCRIBE, rid, subject, option, listener);
106
107         if (__lastErr != ERR_NONE) {
108                 __removeSub(REQ_SUBSCRIBE, rid);
109                 _E("Subscription request failed: %#x", __lastErr);
110                 return __lastErr;
111         }
112
113         return rid;
114 }
115
116 int ContextMonitor::unsubscribe(int ruleId, std::string subject, CtxJson1 option, IContextListener* listener)
117 {
118         int rid = __findSub(REQ_SUBSCRIBE, subject.c_str(), &option);
119         if (rid < 0) {
120                 _D("Invalid unsubscribe request");
121                 return ERR_INVALID_PARAMETER;
122         }
123
124         if (__removeListener(REQ_SUBSCRIBE, rid, listener) <= 0) {
125                 __unsubscribe(subject.c_str(), rid);
126         }
127         _D(YELLOW("Unsubscribe event(rule%d). req%d"), ruleId, rid);
128
129         return ERR_NONE;
130 }
131
132 void ContextMonitor::__unsubscribe(const char *subject, int subscriptionId)
133 {
134         FactRequest *req = new(std::nothrow) FactRequest(REQ_UNSUBSCRIBE, subscriptionId, subject, NULL, NULL);
135         IF_FAIL_VOID_TAG(req, _E, "Memory allocation failed");
136
137         __contextMgr->assignRequest(req);
138         __removeSub(REQ_SUBSCRIBE, subscriptionId);
139 }
140
141 int ContextMonitor::read(std::string subject, CtxJson1 option, IContextListener* listener)
142 {
143         int reqId = __read(subject.c_str(), &option, listener);
144         IF_FAIL_RETURN_TAG(reqId > 0, ERR_OPERATION_FAILED, _E, "Read condition failed");
145         _D(YELLOW("Read condition(%s). req%d"), subject.c_str(), reqId);
146
147         return ERR_NONE;
148 }
149
150 int ContextMonitor::__read(const char* subject, CtxJson1* option, IContextListener* listener)
151 {
152         IF_FAIL_RETURN(subject, ERR_INVALID_PARAMETER);
153
154         int rid = __findSub(REQ_READ, subject, option);
155         if (rid > 0) {
156                 __addListener(REQ_READ, rid, listener);
157                 _D("Duplicated request for %s", subject);
158                 return rid;
159         }
160
161         rid = __generateReqId();
162
163         FactRequest *req = new(std::nothrow) FactRequest(REQ_READ,
164                         rid, subject, option ? option->str().c_str() : NULL, this);
165         IF_FAIL_RETURN_TAG(req, -1, _E, "Memory allocation failed");
166
167         __contextMgr->assignRequest(req);
168         __addSub(REQ_READ, rid, subject, option, listener);
169
170         if (__lastErr != ERR_NONE) {
171                 _E("Read request failed: %#x", __lastErr);
172                 return -1;
173         }
174
175         return rid;
176 }
177
178 bool ContextMonitor::isSupported(std::string subject)
179 {
180         return __contextMgr->isSupported(subject.c_str());
181 }
182
183 bool ContextMonitor::isAllowed(const char *client, const char *subject)
184 {
185         //TODO: re-implement this in the proper 3.0 style
186         //return __contextMgr->isAllowed(client, subject);
187         return true;
188 }
189
190 int ContextMonitor::__findSub(RequestType type, const char* subject, CtxJson1* option)
191 {
192         // @return      request id
193         std::map<int, SubscrInfo*>* map = (type == REQ_SUBSCRIBE)? &__subscrMap : &__readMap;
194
195         CtxJson1 jOpt;
196         if (option) {
197                 jOpt = *option;
198         }
199
200         for (auto it = map->begin(); it != map->end(); ++it) {
201                 if ((*(it->second)).subject == subject && (*(it->second)).option == jOpt) {
202                         return it->first;
203                 }
204         }
205
206         return -1;
207 }
208
209 bool ContextMonitor::__addSub(RequestType type, int sid, const char* subject, CtxJson1* option, IContextListener* listener)
210 {
211         std::map<int, SubscrInfo*>* map = (type == REQ_SUBSCRIBE)? &__subscrMap : &__readMap;
212
213         SubscrInfo *info = new(std::nothrow) SubscrInfo(sid, subject, option);
214         IF_FAIL_RETURN_TAG(info, false, _E, "Memory allocation failed");
215         info->listenerList.push_back(listener);
216
217         map->insert(std::pair<int, SubscrInfo*>(sid, info));
218         return true;
219 }
220
221 void ContextMonitor::__removeSub(RequestType type, const char* subject, CtxJson1* option)
222 {
223         std::map<int, SubscrInfo*>* map = (type == REQ_SUBSCRIBE)? &__subscrMap : &__readMap;
224
225         CtxJson1 jOpt;
226         if (option) {
227                 jOpt = *option;
228         }
229
230         for (auto it = map->begin(); it != map->end(); ++it) {
231                 if ((*(it->second)).subject == subject && (*(it->second)).option == jOpt) {
232                         delete it->second;
233                         map->erase(it);
234                         return;
235                 }
236         }
237 }
238
239 void ContextMonitor::__removeSub(RequestType type, int sid)
240 {
241         std::map<int, SubscrInfo*>* map = (type == REQ_SUBSCRIBE)? &__subscrMap : &__readMap;
242
243         SubscrInfo* info = map->at(sid);
244         info->listenerList.clear();
245
246         delete info;
247         map->erase(sid);
248
249         return;
250 }
251
252 int ContextMonitor::__addListener(RequestType type, int sid, IContextListener* listener)
253 {
254         // @return      number of listeners for the corresponding sid
255         std::map<int, SubscrInfo*>* map = (type == REQ_SUBSCRIBE)? &__subscrMap : &__readMap;
256
257         auto it = map->find(sid);
258
259         SubscrInfo* info = it->second;
260         info->listenerList.push_back(listener);
261
262         return info->listenerList.size();
263 }
264
265 int ContextMonitor::__removeListener(RequestType type, int sid, IContextListener* listener)
266 {
267         // @return      number of listeners for the corresponding sid
268         std::map<int, SubscrInfo*>* map = (type == REQ_SUBSCRIBE)? &__subscrMap : &__readMap;
269
270         auto it = map->find(sid);
271
272         SubscrInfo* info = it->second;
273
274         for (auto it2 = info->listenerList.begin(); it2 != info->listenerList.end(); ++it2) {
275                 if (*it2 == listener) {
276                         info->listenerList.erase(it2);
277                         break;
278                 }
279         }
280
281         return info->listenerList.size();
282 }
283
284 void ContextMonitor::replyResult(int reqId, int error, CtxJson1* requestResult)
285 {
286         _D("Request result received: %d", reqId);
287
288         __lastRid = reqId;
289         __lastErr = error;
290 }
291
292 void ContextMonitor::replyResult(int reqId, int error, const char* subject, CtxJson1* option, CtxJson1* fact)
293 {
294         _D(YELLOW("Condition received: subject(%s), option(%s), fact(%s)"), subject, option->str().c_str(), fact->str().c_str());
295
296         auto it = __readMap.find(reqId);
297         IF_FAIL_VOID_TAG(it != __readMap.end(), _E, "Request id not found");
298
299         SubscrInfo* info = it->second;
300         for (auto it2 = info->listenerList.begin(); it2 != info->listenerList.end(); ++it2) {
301                 (*it2)->onConditionReceived(subject, *option, *fact);
302         }
303
304         __removeSub(REQ_READ, reqId);
305 }
306
307 void ContextMonitor::publishFact(int reqId, int error, const char* subject, CtxJson1* option, CtxJson1* fact)
308 {
309         _D(YELLOW("Event received: subject(%s), option(%s), fact(%s)"), subject, option->str().c_str(), fact->str().c_str());
310
311         auto it = __subscrMap.find(reqId);
312         IF_FAIL_VOID_TAG(it != __subscrMap.end(), _E, "Request id not found");
313
314         SubscrInfo* info = it->second;
315         for (auto it2 = info->listenerList.begin(); it2 != info->listenerList.end(); ++it2) {
316                 (*it2)->onEventReceived(subject, *option, *fact);
317         }
318 }