6c6f863713a49263c8e6b704f736e1d633a1a361
[contrib/iotivity.git] / service / simulator / src / server / resource_update_automation.cpp
1 /******************************************************************
2  *
3  * Copyright 2015 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
21 #include "resource_update_automation.h"
22 #include "simulator_single_resource_impl.h"
23 #include "attribute_generator.h"
24 #include "simulator_exceptions.h"
25 #include "simulator_logger.h"
26 #include "logger.h"
27
28 #define ATAG "ATTRIBUTE_AUTOMATION"
29 #define RTAG "RESOURCE_AUTOMATION"
30
31 #define SLEEP_FOR(X) if (X > 0) std::this_thread::sleep_for(std::chrono::milliseconds(X));
32
33 AttributeUpdateAutomation::AttributeUpdateAutomation(int id, SimulatorSingleResource *resource,
34         const SimulatorResourceModel::Attribute &attribute, AutomationType type, int interval,
35         updateCompleteCallback callback, std::function<void (const int)> finishedCallback)
36     :   m_resource(resource),
37         m_type(type),
38         m_id(id),
39         m_stopRequested(false),
40         m_updateInterval(interval),
41         m_attributeGen(attribute),
42         m_callback(callback),
43         m_finishedCallback(finishedCallback),
44         m_thread(nullptr)
45 {
46     if (m_updateInterval < 0)
47     {
48         m_updateInterval = 0;
49     }
50 }
51
52 void AttributeUpdateAutomation::start()
53 {
54     m_thread = new std::thread(&AttributeUpdateAutomation::updateAttribute, this);
55 }
56
57 void AttributeUpdateAutomation::stop()
58 {
59     m_stopRequested = true;
60     if (m_thread)
61         m_thread->join();
62 }
63
64 void AttributeUpdateAutomation::updateAttribute()
65 {
66     SimulatorSingleResourceImpl *resourceImpl =
67         dynamic_cast<SimulatorSingleResourceImpl *>(m_resource);
68
69     if (!resourceImpl)
70         return;
71
72     do
73     {
74         try
75         {
76             SimulatorResourceModel::Attribute attribute;
77             while (!m_stopRequested && true == m_attributeGen.next(attribute))
78             {
79                 if (false == m_resource->updateAttributeValue(attribute))
80                 {
81                     OC_LOG_V(ERROR, ATAG, "Failed to update the attribute![%s]", attribute.getName().c_str());
82                     continue;
83                 }
84                 resourceImpl->notifyApp();
85
86                 SLEEP_FOR(m_updateInterval);
87             }
88
89             m_attributeGen.reset();
90         }
91         catch (SimulatorException &e)
92         {
93             break;
94         }
95     }
96     while (!m_stopRequested && AutomationType::RECURRENT == m_type);
97
98     if (!m_stopRequested)
99     {
100         OC_LOG_V(DEBUG, ATAG, "Attribute:%s automation is completed!", m_attrName.c_str());
101         SIM_LOG(ILogger::INFO, "Automation of " << m_attrName << " attribute is completed.");
102     }
103
104     // Notify application through callback
105     if (m_callback)
106         m_callback(m_resource->getURI(), m_id);
107
108     if (m_finishedCallback && !m_stopRequested)
109         m_finishedCallback(m_id);
110 }
111
112 ResourceUpdateAutomation::ResourceUpdateAutomation(int id, SimulatorSingleResource *resource,
113         AutomationType type, int interval, updateCompleteCallback callback,
114         std::function<void (const int)> finishedCallback)
115     :   m_resource(resource),
116         m_type(type),
117         m_id(id),
118         m_stopRequested(false),
119         m_updateInterval(interval),
120         m_callback(callback),
121         m_finishedCallback(finishedCallback),
122         m_thread(nullptr) {}
123
124 void ResourceUpdateAutomation::start()
125 {
126     std::vector<SimulatorResourceModel::Attribute> attributes;
127     for (auto &attributeEntry : m_resource->getResourceModel().getAttributes())
128     {
129         attributes.push_back(attributeEntry.second);
130     }
131
132     if (0 == attributes.size())
133     {
134         OC_LOG(ERROR, RTAG, "Resource has zero attributes!");
135         throw SimulatorException(SIMULATOR_ERROR, "Resource has zero attributes!");
136     }
137
138     m_thread = new std::thread(&ResourceUpdateAutomation::updateAttributes, this, attributes);
139 }
140
141 void ResourceUpdateAutomation::stop()
142 {
143     m_stopRequested = true;
144     if (m_thread)
145         m_thread->join();
146 }
147
148 void ResourceUpdateAutomation::updateAttributes(
149     std::vector<SimulatorResourceModel::Attribute> attributes)
150 {
151     SimulatorSingleResourceImpl *resourceImpl =
152         dynamic_cast<SimulatorSingleResourceImpl *>(m_resource);
153
154     if (!resourceImpl)
155         return;
156
157     do
158     {
159         AttributeCombinationGen attrCombGen(attributes);
160         SimulatorResourceModel resModel;
161         while (!m_stopRequested && attrCombGen.next(resModel))
162         {
163             for (auto &attributeEntry : resModel.getAttributes())
164             {
165                 resourceImpl->updateAttributeValue(attributeEntry.second);
166             }
167
168             resourceImpl->notifyApp();
169             SLEEP_FOR(m_updateInterval);
170         }
171     }
172     while (!m_stopRequested && AutomationType::RECURRENT == m_type);
173
174     if (!m_stopRequested)
175     {
176         SIM_LOG(ILogger::INFO, "Resource update automation complete [id: " << m_id << "]");
177     }
178
179     // Notify application
180     if (m_callback)
181         m_callback(m_resource->getURI(), m_id);
182
183     if (m_finishedCallback && !m_stopRequested)
184         m_finishedCallback(m_id);
185 }
186