Imported Upstream version 0.9.1
[platform/upstream/iotivity.git] / service / soft-sensor-manager / SSMCore / src / SensorProcessor / ContextExecutor.cpp
1 /******************************************************************
2 *
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
4 *
5 *
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ******************************************************************/
20 #include "ContextExecutor.h"
21
22 SSMRESULT CContextExecutor::finalConstruct()
23 {
24     SSMRESULT res = SSM_E_FAIL;
25
26     ctxEvent = NULL;
27
28     SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_ITasker, (IBase **)&m_pTasker));
29     SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IContextRepository, (IBase **)&m_pContextRepository));
30     SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IContextDataReader, (IBase **)&m_pContextDataReader));
31
32     SSM_CLEANUP_ASSERT(m_pContextRepository->registerResourceFinderEvent(this));
33
34 CLEANUP:
35     return res;
36 }
37
38 void CContextExecutor::finalRelease()
39 {
40 }
41
42 void CContextExecutor::registerCallback(ICtxEvent *pEvent)
43 {
44     ctxEvent = pEvent;
45 }
46
47 //Data from soft sensors
48 void CContextExecutor::addOutput(std::vector<ContextData> contextData)
49 {
50     //LOGE("ADDOUTPUT");
51     std::map<std::string, CallbackData>::iterator   itor;
52     std::string type = contextData[0].rootName;
53
54     //TODO: name must be a this soft sensors identifier
55     //m_mtxRequestedContextCallback.Lock();
56     itor = m_requestedContextCallback.find(type);
57     if (itor != m_requestedContextCallback.end())
58     {
59         TypeofEvent callType = itor->second.m_callType;
60         itor->second.m_pCallbackEvent->onEvent(type, callType, contextData);
61         if (callType == SSM_ONCE)
62         {
63             unregisterContext(callType, m_registeredResources[type], this);
64         }
65
66     }
67     //m_mtxRequestedContextCallback.Unlock();
68 }
69
70 void CContextExecutor::getDataFromDatabase(std::string modelName, int startIndex, int count,
71         std::vector<ContextData> *data, int *pLastIndex)
72 {
73     m_pContextDataReader->getContextData(modelName, startIndex, count, data, pLastIndex);
74 }
75
76 void CContextExecutor::registerContext(TypeofEvent callType, ISSMResource *pSSMResource,
77                                        IEvent *pEvent)
78 {
79     //will make check routine for One resource has callbacks.
80     std::vector<ISSMResource *>  baseList;
81
82     CallbackData callbackData(callType, pSSMResource->name, pEvent);
83
84     //m_mtxRequestedContextCallback.Lock();
85     m_registeredResources[pSSMResource->type] = pSSMResource;
86     m_requestedContextCallback[pSSMResource->type] = callbackData;
87     //m_mtxRequestedContextCallback.Unlock();
88
89     //This is stand-alone sensor
90     if (pSSMResource->inputList.size() == 0)
91     {
92         //Let sensors work
93         std::vector<ContextData> inputData;
94         switch (pSSMResource->location)
95         {
96             case SENSOR_LOCATION_LOCAL:
97                 runLogic(inputData, pSSMResource->type);
98                 break;
99
100             case SENSOR_LOCATION_REMOTE:
101                 //Let observer work!
102                 m_pContextRepository->startObserveResource(pSSMResource, this);
103                 break;
104         }
105     }
106
107     m_pContextRepository->getPrimitiveSensorList(&baseList);
108     m_pContextRepository->getSoftSensorList(&baseList);
109
110     for (unsigned int i = 0; i < pSSMResource->inputList.size(); ++i)
111     {
112         ISSMResource *pKeyResource = NULL;
113         if (findString(&baseList, pSSMResource->inputList[i],
114                        &pKeyResource) != SSM_E_FAIL) //if element of inputList is in the primitive resources.
115         {
116             if (m_relatedSoftSensor.find(pKeyResource->type) != m_relatedSoftSensor.end()) //already exists
117             {
118                 //EXIST!!!!
119                 //check related Context needs insert or not. if softSensor resource is not a member of related context then insert.
120                 std::vector<std::string> softSensorList = m_relatedSoftSensor[pKeyResource->type];
121
122                 for (unsigned int j = 0; j < softSensorList.size(); ++j)
123                 {
124                     if (softSensorList[j].compare(pSSMResource->type) != 0)
125                     {
126                         m_relatedSoftSensor[pKeyResource->type].push_back(pSSMResource->type);
127                         break;
128                     }
129                 }
130             }
131             else // If first time
132             {
133                 //NO EXIST!!!!
134                 //insert resource in the all map and vector
135                 m_relatedSoftSensor[pKeyResource->type].push_back(pSSMResource->type);
136
137                 //Recursive call
138                 registerContext(callType, pKeyResource, this);
139             }
140         }
141         else //unable to find installed sensors. take it to keep list
142         {
143             m_mapResourceLookup[pSSMResource->inputList[i]].push_back(CallbackData(callType, pSSMResource->type,
144                     this));
145         }
146     }
147 }
148
149 void CContextExecutor::onExecute(void *pArg)
150 {
151     intptr_t         *pMessage = (intptr_t *)pArg;
152
153     RESOURCE_EVENT_TYPE     eventType = (RESOURCE_EVENT_TYPE)pMessage[0];
154     ISSMResource            *pResource = (ISSMResource *)pMessage[1];
155
156     switch (eventType)
157     {
158         case SSM_EVENT_NORMAL:
159             break;
160
161         case SSM_EVENT_ADDED:
162             if (m_mapResourceLookup.find(pResource->type) != m_mapResourceLookup.end())
163             {
164                 CallbackData        *callBack = NULL;
165
166                 for (size_t i = 0; i < m_mapResourceLookup[pResource->type].size(); i++)
167                 {
168                     callBack = &m_mapResourceLookup[pResource->type][i];
169
170                     m_relatedSoftSensor[pResource->type].push_back(callBack->m_name);
171
172                     registerContext(callBack->m_callType, pResource, callBack->m_pCallbackEvent);
173                 }
174
175                 m_mapResourceLookup.erase(m_mapResourceLookup.find(pResource->type));
176             }
177             break;
178
179         case SSM_REMOVED:
180             break;
181
182         case SSM_UPDATED:
183             break;
184
185         default:
186             break;
187     }
188 }
189
190 void CContextExecutor::onTerminate(void *pArg)
191 {
192     intptr_t         *pMessage = (intptr_t *)pArg;
193
194     delete[] pMessage;
195 }
196
197 int CContextExecutor::onResourceEvent(RESOURCE_EVENT_TYPE eventType, ISSMResource *pSSMResource,
198                                       std::string info)
199 {
200     intptr_t          *pMessage = new intptr_t [2];
201
202     pMessage[0] = eventType;
203     pMessage[1] = reinterpret_cast<intptr_t>(pSSMResource);
204     return (int)m_pTasker->addTask(this, (void *)pMessage);
205 }
206
207 SSMRESULT CContextExecutor::findString(std::vector<ISSMResource *> *sList, const std::string str,
208                                        ISSMResource **ppResource)
209 {
210     SSMRESULT ret = SSM_E_FAIL;
211     for (unsigned int i = 0 ; i < sList->size() ; ++i)
212     {
213         if ((*sList)[i]->type == str)
214         {
215             *ppResource = (*sList)[i];
216             ret = SSM_S_OK;
217             break;
218         }
219     }
220     return ret;
221 }
222
223 std::map<std::string, std::vector<ContextData> >  CContextExecutor::getPreparedContextList(
224     std::string primitiveSensor)
225 {
226     //check m_relatedSoftSensor / apply timestamp
227
228     SSMRESULT ret = SSM_E_FAIL;
229
230     std::map<std::string, std::vector<ContextData> >    returnData;
231     std::vector<ContextData>                            contextDataList;
232
233     for (unsigned int i = 0; i < m_relatedSoftSensor[primitiveSensor].size(); ++i)
234     {
235         std::string softSensorName = m_relatedSoftSensor[primitiveSensor][i];
236         if (m_registeredResources.find(softSensorName) != m_registeredResources.end())
237         {
238             ret = SSM_S_OK;
239             std::vector<std::string> inputList = m_registeredResources[softSensorName]->inputList;
240             for (unsigned int j = 0; j < inputList.size(); j++) //check all "inputlist" arrived or not
241             {
242                 if (m_storedPrimitiveSensorData.find(inputList[j]) == m_storedPrimitiveSensorData.end())
243                 {
244                     //Still we have partial data
245                     ret = SSM_E_FAIL;
246                     break;
247                 }
248                 else
249                 {
250                     //Copy all properties of current primitiveSensor data to outputs
251                     for (std::vector<ContextData>::iterator itor = m_storedPrimitiveSensorData[inputList[j]].begin();
252                          itor != m_storedPrimitiveSensorData[inputList[j]].end(); ++itor)
253                     {
254                         contextDataList.push_back(*itor);
255                     }
256                 }
257             }
258
259             //We have all inputs
260             if (ret == SSM_S_OK)
261             {
262                 returnData.insert(std::make_pair(softSensorName, contextDataList));
263             }
264             contextDataList.clear();
265         }
266     }
267
268     return returnData;
269 }
270
271 //Data from every primitive sensors
272 int CContextExecutor::onEvent(std::string type, TypeofEvent callType,
273                               std::vector<ContextData> ctxData)
274 {
275     //std::string root_name = ctxData.at(0).root_name; //-> deviceId+ctxData.root_name
276
277     if (m_relatedSoftSensor.find(type) != m_relatedSoftSensor.end()) //already registered?
278     {
279         //update recent values(overwrite)
280         m_storedPrimitiveSensorData[type] = ctxData;
281
282         //find soft sensor
283         std::map<std::string, std::vector<ContextData> > readyContextList = getPreparedContextList(type);
284
285         //Run SoftSensor!  readyContextList has all data for run
286         std::map<std::string, std::vector<ContextData> >::iterator iter;
287         for (iter = readyContextList.begin(); iter != readyContextList.end(); ++iter)
288         {
289             std::string softSensorName = iter->first;
290             std::vector<ContextData> inputData = iter->second;
291
292             runLogic(inputData, softSensorName);
293         }
294     }
295     else if (m_registeredResources.find(type) != m_registeredResources.end()) //This data is primitive
296     {
297         addOutput(ctxData);
298     }
299
300     return SSM_S_OK;
301 }
302
303 void  CContextExecutor::unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
304         IEvent *pEvent)
305 {
306     std::vector<ISSMResource *> baseList;
307
308     //////////
309     ///TODO: Need to clean up m_mapResourceLookup list
310     //////////
311
312     //This is primitive sensor
313     if (pSSMResource->inputList.size() == 0)
314     {
315         //Let sensors work
316         std::vector<ContextData> inputData;
317         switch (pSSMResource->location)
318         {
319             case SENSOR_LOCATION_LOCAL:
320                 //TODO: Must free soft sensor
321                 if (m_libraryList.find(pSSMResource->type) != m_libraryList.end() && callType != SSM_ONCE)
322                 {
323                     m_pContextRepository->unloadSoftSensor(m_libraryList[pSSMResource->type]);
324                     m_libraryList.erase(m_libraryList.find(pSSMResource->type));
325                 }
326
327                 if (m_ctxEventList.find(pSSMResource->type) != m_ctxEventList.end())
328                 {
329                     m_ctxEventList.erase(m_ctxEventList.find(pSSMResource->type));
330                 }
331                 break;
332
333             case SENSOR_LOCATION_REMOTE:
334                 //Let observer stop work!
335                 m_pContextRepository->stopObserveResource(pSSMResource);
336                 break;
337         }
338     }
339
340     //m_mtxRequestedContextCallback.Lock();
341     if (m_requestedContextCallback.find(pSSMResource->type) != m_requestedContextCallback.end())
342     {
343         m_requestedContextCallback.erase(m_requestedContextCallback.find(pSSMResource->type));
344     }
345     if (m_registeredResources.find(pSSMResource->type) != m_registeredResources.end())
346     {
347         m_registeredResources.erase(m_registeredResources.find(pSSMResource->type));
348     }
349     //m_mtxRequestedContextCallback.Unlock();
350
351     //TODO: support multiple concurrent query reference
352     m_pContextRepository->getPrimitiveSensorList(&baseList);
353     m_pContextRepository->getSoftSensorList(&baseList);
354
355     for (unsigned int i = 0 ; i < pSSMResource->inputList.size() ; ++i)
356     {
357         ISSMResource *pPrimitiveSensor = NULL;
358         if (findString(&baseList, pSSMResource->inputList[i], &pPrimitiveSensor) != SSM_E_FAIL)
359         {
360             std::vector<std::string> *softSensorList = &m_relatedSoftSensor[pPrimitiveSensor->type];
361             for (unsigned int j = 0; j < softSensorList->size(); ++j)
362             {
363                 if (!(*softSensorList)[j].compare(pSSMResource->type))
364                 {
365                     softSensorList->erase(softSensorList->begin() + j);
366
367                     if (softSensorList->size() == 0) //no more related context.
368                     {
369                         m_relatedSoftSensor.erase(m_relatedSoftSensor.find(pPrimitiveSensor->type));
370
371                         //Recursive call
372                         unregisterContext(callType, pPrimitiveSensor, this);
373                         break;
374                     }
375                 }
376             }
377         }
378     }
379 }
380
381 //Called when soft sensor try to work
382 void CContextExecutor::runLogic(std::vector<ContextData> inputData, std::string softSensor)
383 {
384     m_mtxLibraryIO.lock();
385     if (m_ctxEventList.find(softSensor) == m_ctxEventList.end())
386     {
387         void *hSoftSensor = NULL;
388         if (m_pContextRepository->loadSoftSensor(softSensor, this, &hSoftSensor) == SSM_S_OK)
389         {
390             m_libraryList[softSensor] = hSoftSensor;
391             m_ctxEventList[softSensor] = ctxEvent;
392             m_ctxEventList[softSensor]->onCtxEvent(SPF_START, inputData);
393         }
394     }
395     else
396     {
397         m_ctxEventList[softSensor]->onCtxEvent(SPF_START, inputData);
398     }
399     m_mtxLibraryIO.unlock();
400 }