e77156193e1d54df629e5a944509fe065c7b9736
[profile/ivi/automotive-message-broker.git] / ambd / core.cpp
1 /*
2     Copyright (C) 2012  Intel Corporation
3
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Lesser General Public
6     License as published by the Free Software Foundation; either
7     version 2.1 of the License, or (at your option) any later version.
8
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Lesser General Public License for more details.
13
14     You should have received a copy of the GNU Lesser General Public
15     License along with this library; if not, write to the Free Software
16     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19
20 #include "core.h"
21 #include <functional>
22 #include <glib.h>
23 #include "listplusplus.h"
24 #include "debugout.h"
25
26 using namespace std::placeholders;
27
28 int lastpps=0;
29
30 static int PPSUpdate(void* data)
31 {
32         int* pps = (int*)data;
33
34         int temp = *pps;
35
36         if(temp > 0 && temp != lastpps)
37         {
38                 lastpps = temp;
39                 DebugOut(1)<<"Property updates per second: "<<temp<<endl;
40         }
41
42         *pps = 0;
43 }
44
45 Core::Core()
46         :propertiesPerSecond(0)
47 {
48         g_timeout_add(1000,PPSUpdate,&propertiesPerSecond);
49 }
50
51 Core::~Core()
52 {
53         std::vector<AbstractSink*> toDelete;
54         for(auto itr = mSinks.begin(); itr != mSinks.end(); itr++)
55         {
56                 AbstractSink* sink = *itr;
57                 toDelete.push_back(sink);
58         }
59
60         for(int i=0; i<toDelete.size(); i++)
61         {
62                 delete toDelete[i];
63         }
64 }
65
66
67 void Core::setSupported(PropertyList supported, AbstractSource* source)
68 {
69
70         if(!ListPlusPlus<AbstractSource*>(&mSources).contains(source))
71                 mSources.push_back(source);
72                 
73         for(PropertyList::iterator itr = supported.begin(); itr != supported.end(); itr++)
74         {
75                 if(!ListPlusPlus<VehicleProperty::Property>(&mMasterPropertyList).contains((*itr)))
76                 {
77                         DebugOut()<<__FUNCTION__<<"() adding support for property "<<(*itr)<<endl;
78                         mMasterPropertyList.push_back((*itr));
79                 }
80         }
81
82         /// tell all new sinks about the newly supported properties.
83
84         for(SinkList::iterator itr = mSinks.begin(); itr != mSinks.end(); itr++)
85         {
86                 (*itr)->supportedChanged(mMasterPropertyList);
87         }
88
89         /// iterate through subscribed properties and resubscribe.  This catches newly supported properties in the process.
90
91         for(map<VehicleProperty::Property, SinkList>::iterator itr = propertySinkMap.begin(); itr != propertySinkMap.end(); itr++)
92         {
93                 VehicleProperty::Property  property = (*itr).first;
94
95                 for(SourceList::iterator source = mSources.begin(); source != mSources.end(); source++)
96                 {
97                         PropertyList properties = (*source)->supported();
98
99                         if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(property))
100                         {
101                                 (*source)->subscribeToPropertyChanges(property);
102                         }
103                 }
104         }
105 }
106
107
108 void Core::updateSupported(PropertyList added, PropertyList removed)
109 {
110         
111         /// add the newly supported to master list
112         
113         for(PropertyList::iterator itr = added.begin(); itr != added.end(); itr++)
114         {
115                 if(ListPlusPlus<VehicleProperty::Property>(&added).contains(*itr))
116                 {
117                         mMasterPropertyList.push_back(*itr);
118                 }
119         }
120         
121         /// removed no longer supported properties from master list.
122         
123         for(PropertyList::iterator itr = removed.begin(); itr != removed.end(); itr++)
124         {
125                 ListPlusPlus<VehicleProperty::Property>(&mMasterPropertyList).removeOne(*itr);
126         }
127         
128         /// tell all new sinks about the newly supported properties.
129         
130         for(SinkList::iterator itr = mSinks.begin(); itr != mSinks.end(); itr++)
131         {
132                 (*itr)->supportedChanged(mMasterPropertyList);
133         }
134         
135         /// iterate through subscribed properties and resubscribe.  This catches newly supported properties in the process.
136         
137         for(map<VehicleProperty::Property, SinkList>::iterator itr = propertySinkMap.begin(); itr != propertySinkMap.end(); itr++)
138         {
139                 VehicleProperty::Property  property = (*itr).first;
140                 
141                 for(SourceList::iterator source = mSources.begin(); source != mSources.end(); source++)
142                 {
143                         PropertyList properties = (*source)->supported();
144                         
145                         if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(property))
146                         {
147                                 (*source)->subscribeToPropertyChanges(property);
148                         }
149                 }
150         }
151 }
152
153 void Core::updateProperty(VehicleProperty::Property property, AbstractPropertyType *value, std::string uuid)
154 {
155         SinkList list = propertySinkMap[property];
156         
157         DebugOut()<<__FUNCTION__<<"() there are "<<list.size()<<" sinks connected to property: "<<property<<endl;
158
159         propertiesPerSecond++;
160
161
162         for(SinkList::iterator itr = list.begin(); itr != list.end(); itr++)
163         {
164                 (*itr)->propertyChanged(property, value, uuid);
165         }
166 }
167
168 void Core::registerSink(AbstractSink *self)
169 {
170         if(!ListPlusPlus<AbstractSink*>(&mSinks).contains(self))
171         {
172                 mSinks.push_back(self);
173         }
174 }
175
176 void Core::unregisterSink(AbstractSink *self)
177 {
178         if(ListPlusPlus<AbstractSink*>(&mSinks).contains(self))
179         {
180                 ListPlusPlus<AbstractSink*>(&mSinks).removeOne(self);
181         }
182 }
183
184
185 AsyncPropertyReply *Core::getPropertyAsync(AsyncPropertyRequest request)
186 {
187         AsyncPropertyReply * reply = new AsyncPropertyReply(request);
188
189         for(SourceList::iterator itr = mSources.begin(); itr != mSources.end(); itr++)
190         {
191                 AbstractSource* src = (*itr);
192                 PropertyList properties = src->supported();
193                 int supportedOps = src->supportedOperations();
194
195                 bool supportsGet = supportedOps & AbstractSource::Get;
196
197                 if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(request.property) && supportsGet && (request.sourceUuid == "" || request.sourceUuid == src->uuid()))
198                 {
199                         src->getPropertyAsync(reply);
200
201                         /** right now the owner of the reply becomes the requestor that called this method.
202                          *  reply will become invalid after the first reply. */
203                         return reply;
204                 }
205         }
206
207         return reply;
208 }
209
210 AsyncRangePropertyReply *Core::getRangePropertyAsync(AsyncRangePropertyRequest request)
211 {
212         AsyncRangePropertyReply * reply = new AsyncRangePropertyReply(request);
213
214         for(SourceList::iterator itr = mSources.begin(); itr != mSources.end(); itr++)
215         {
216                 AbstractSource* src = (*itr);
217                 PropertyList properties = src->supported();
218                 if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(request.property)
219                                 && (src->supportedOperations() & AbstractSource::GetRanged)
220                                 && (request.sourceUuid == "" || request.sourceUuid == src->uuid()))
221                 {
222                         src->getRangePropertyAsync(reply);
223                 }
224         }
225
226         return reply;
227 }
228
229 AsyncPropertyReply * Core::setProperty(AsyncSetPropertyRequest request)
230 {
231         for(SourceList::iterator itr = mSources.begin(); itr != mSources.end(); itr++)
232         {
233                 AbstractSource* src = (*itr);
234                 PropertyList properties = src->supported();
235                 if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(request.property) && src->supportedOperations() & AbstractSource::Set)
236                 {
237                         return src->setProperty(request);
238                 }
239         }
240
241         DebugOut(0)<<"Error: setProperty opration failed"<<endl;
242         return NULL;
243 }
244
245 void Core::subscribeToProperty(VehicleProperty::Property property, AbstractSink* self)
246 {
247         DebugOut(1)<<"Subscribing to: "<<property<<endl;
248
249         /** TODO: Change behavior of subscribe to subscribe even if no sources provide a
250          *  given property.  When subscribers come online with support, core should tell
251          *  the sources what properties have already been subscribed to.
252          */
253
254         /*if(!ListPlusPlus<VehicleProperty::Property>(&mMasterPropertyList).contains((property)))
255         {
256                 DebugOut(1)<<__FUNCTION__<<"(): property not supported: "<<property<<endl;
257                 return; 
258         }*/
259         
260         if(propertySinkMap.find(property) == propertySinkMap.end())
261         {
262                 propertySinkMap[property] = SinkList();
263         }
264         
265         SinkList list = propertySinkMap[property];
266         
267         if(!ListPlusPlus<AbstractSink*>(&list).contains(self))
268         {
269                 propertySinkMap[property].push_back(self);
270         }
271         
272         for(SourceList::iterator itr = mSources.begin(); itr != mSources.end(); itr++)
273         {
274                 AbstractSource* src = (*itr);
275                 PropertyList properties = src->supported();
276                 if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(property))
277                 {
278                         src->subscribeToPropertyChanges(property);
279                 }
280         }
281 }
282
283 void Core::unsubscribeToProperty(VehicleProperty::Property property, AbstractSink* self)
284 {
285         if(propertySinkMap.find(property) == propertySinkMap.end())
286         {
287                 DebugOut(1)<<__FUNCTION__<<"property not supported: "<<property<<endl;
288                 return; 
289         }
290                 
291         ListPlusPlus<AbstractSink*>(&propertySinkMap[property]).removeOne(self);
292
293         /// Now we check to see if this is the last subscriber
294         if(propertySinkMap.find(property) == propertySinkMap.end())
295         {
296                 for(SourceList::iterator itr = mSources.begin(); itr != mSources.end(); itr++)
297                 {
298                         AbstractSource* src = (*itr);
299                         PropertyList properties = src->supported();
300
301                         if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(property))
302                         {
303                                 src->unsubscribeToPropertyChanges(property);
304                         }
305                 }
306         }
307 }
308