Each provider handler is self-destructed if there is no remaining request
[platform/core/context/context-service.git] / src / ProviderHandler.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 <glib.h>
18 #include <Types.h>
19 #include "access_control/Privilege.h"
20 #include "Request.h"
21 #include "ProviderHandler.h"
22
23 #define DELETE_DELAY 10
24
25 using namespace ctx;
26
27 std::map<std::string, ProviderHandler*> ProviderHandler::__instanceMap;
28
29 ProviderHandler::ProviderHandler(const std::string &subject) :
30         __subject(subject),
31         __deleteScheduled(false)
32 {
33         _D("Subject: %s", __subject.c_str());
34 }
35
36 ProviderHandler::~ProviderHandler()
37 {
38         _D("Subject: %s", __subject.c_str());
39
40         for (RequestInfo*& info : __subscribeRequests) {
41                 delete info;
42         }
43         __subscribeRequests.clear();
44
45         for (RequestInfo*& info : __readRequests) {
46                 delete info;
47         }
48         __readRequests.clear();
49
50         delete __provider;
51 }
52
53 /* TODO: Return proper error code */
54 ProviderHandler* ProviderHandler::getInstance(std::string subject, bool force)
55 {
56         InstanceMap::iterator it = __instanceMap.find(subject);
57
58         if (it != __instanceMap.end())
59                 return it->second;
60
61         if (!force)
62                 return NULL;
63
64         ProviderHandler *handle = new(std::nothrow) ProviderHandler(subject);
65         IF_FAIL_RETURN_TAG(handle, NULL, _E, "Memory allocation failed");
66
67         if (!handle->__loadProvider()) {
68                 delete handle;
69                 return NULL;
70         }
71
72         __instanceMap[subject] = handle;
73
74         return handle;
75 }
76
77 void ProviderHandler::purge()
78 {
79         for (InstanceMap::iterator it = __instanceMap.begin(); it != __instanceMap.end(); ++it) {
80                 delete it->second;
81         }
82
83         __instanceMap.clear();
84 }
85
86 bool ProviderHandler::isSupported()
87 {
88         return __provider->isSupported();
89 }
90
91 bool ProviderHandler::isAllowed(const Credentials *creds)
92 {
93         IF_FAIL_RETURN(creds, true);    /* In case of internal requests */
94
95         std::vector<const char*> priv;
96         __provider->getPrivilege(priv);
97
98         for (unsigned int i = 0; i < priv.size(); ++i) {
99                 if (!privilege_manager::isAllowed(creds, priv[i]))
100                         return false;
101         }
102
103         return true;
104 }
105
106 void ProviderHandler::subscribe(RequestInfo *request)
107 {
108         _I(CYAN("'%s' subscribes '%s' (RID-%d)"), request->getClient(), __subject.c_str(), request->getId());
109
110         Json requestResult;
111         int error = __provider->subscribe(request->getDescription().str(), &requestResult);
112
113         if (!request->reply(error, requestResult) || error != ERR_NONE) {
114                 delete request;
115                 return;
116         }
117
118         __subscribeRequests.push_back(request);
119 }
120
121 void ProviderHandler::unsubscribe(RequestInfo *request)
122 {
123         _I(CYAN("'%s' unsubscribes '%s' (RID-%d)"), request->getClient(), __subject.c_str(), request->getId());
124
125         /* Search the subscribe request to be removed */
126         auto target = __findRequest(__subscribeRequests, request->getClient(), request->getId());
127         if (target == __subscribeRequests.end()) {
128                 _W("Unknown request");
129                 delete request;
130                 return;
131         }
132
133         /* Keep the pointer to the request found */
134         RequestInfo *reqFound = *target;
135
136         /* Remove the request from the list */
137         __subscribeRequests.erase(target);
138
139         /* Check if there exist the same requests */
140         if (__findRequest(__subscribeRequests, reqFound->getDescription()) != __subscribeRequests.end()) {
141                 /* Do not stop detecting the subject */
142                 _D("A same request from '%s' exists", reqFound->getClient());
143                 request->reply(ERR_NONE);
144                 delete request;
145                 delete reqFound;
146                 return;
147         }
148
149         /* Stop detecting the subject */
150         int error = __provider->unsubscribe(reqFound->getDescription());
151         request->reply(error);
152         delete request;
153         delete reqFound;
154
155         /* If idle, self destruct */
156         __scheduleToDelete();
157 }
158
159 void ProviderHandler::read(RequestInfo *request)
160 {
161         _I(CYAN("'%s' reads '%s' (RID-%d)"), request->getClient(), __subject.c_str(), request->getId());
162
163         Json requestResult;
164         int error = __provider->read(request->getDescription().str(), &requestResult);
165
166         if (!request->reply(error, requestResult) || error != ERR_NONE) {
167                 delete request;
168                 return;
169         }
170
171         __readRequests.push_back(request);
172 }
173
174 void ProviderHandler::write(RequestInfo *request)
175 {
176         _I(CYAN("'%s' writes '%s' (RID-%d)"), request->getClient(), __subject.c_str(), request->getId());
177
178         Json requestResult;
179         int error = __provider->write(request->getDescription(), &requestResult);
180
181         request->reply(error, requestResult);
182         delete request;
183
184         /* If idle, self destruct */
185         __scheduleToDelete();
186 }
187
188 bool ProviderHandler::publish(Json &option, int error, Json &dataUpdated)
189 {
190         auto end = __subscribeRequests.end();
191         auto target = __findRequest(__subscribeRequests.begin(), end, option);
192
193         while (target != end) {
194                 if (!(*target)->publish(error, dataUpdated)) {
195                         return false;
196                 }
197                 target = __findRequest(++target, end, option);
198         }
199
200         return true;
201 }
202
203 bool ProviderHandler::replyToRead(Json &option, int error, Json &dataRead)
204 {
205         auto end = __readRequests.end();
206         auto target = __findRequest(__readRequests.begin(), end, option);
207         auto prev = target;
208
209         Json dummy;
210
211         while (target != end) {
212                 (*target)->reply(error, dummy, dataRead);
213                 prev = target;
214                 target = __findRequest(++target, end, option);
215
216                 delete *prev;
217                 __readRequests.erase(prev);
218         }
219
220         /* If idle, self destruct */
221         __scheduleToDelete();
222
223         return true;
224 }
225
226 bool ProviderHandler::__loadProvider()
227 {
228         __provider = __loader.load(__subject.c_str());
229         return (__provider != NULL);
230 }
231
232 bool ProviderHandler::__idle()
233 {
234         return __subscribeRequests.empty() && __readRequests.empty();
235 }
236
237 void ProviderHandler::__scheduleToDelete()
238 {
239         if (!__deleteScheduled && __idle()) {
240                 __deleteScheduled = true;
241                 g_timeout_add_seconds(DELETE_DELAY, __deletor, this);
242                 _D("Delete scheduled for '%s' (%#x)", __subject.c_str(), this);
243         }
244 }
245
246 gboolean ProviderHandler::__deletor(gpointer data)
247 {
248         ProviderHandler *handle = static_cast<ProviderHandler*>(data);
249
250         if (handle->__idle()) {
251                 __instanceMap.erase(handle->__subject);
252                 delete handle;
253                 return FALSE;
254         }
255
256         handle->__deleteScheduled = false;
257         return FALSE;
258 }
259
260 ProviderHandler::RequestList::iterator
261 ProviderHandler::__findRequest(RequestList &reqList, Json &option)
262 {
263         return __findRequest(reqList.begin(), reqList.end(), option);
264 }
265
266 ProviderHandler::RequestList::iterator
267 ProviderHandler::__findRequest(RequestList &reqList, std::string client, int reqId)
268 {
269         for (auto it = reqList.begin(); it != reqList.end(); ++it) {
270                 if (client == (*it)->getClient() && reqId == (*it)->getId()) {
271                         return it;
272                 }
273         }
274         return reqList.end();
275 }
276
277 ProviderHandler::RequestList::iterator
278 ProviderHandler::__findRequest(RequestList::iterator begin, RequestList::iterator end, Json &option)
279 {
280         for (auto it = begin; it != end; ++it) {
281                 if (option == (*it)->getDescription()) {
282                         return it;
283                 }
284         }
285         return end;
286 }