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