added overload for subscribe that includes a zone filter. it is unimplemented in...
[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                 AbstractSink* sink = *itr;
165
166                 auto isFiltered = filteredSourceSinkMap.find(sink);
167
168                 if(isFiltered != filteredSourceSinkMap.end() )
169                 {
170
171                         std::string u = filteredSourceSinkMap[sink][property];
172                         DebugOut()<<"Property ("<<property<<") for sink is filtered for source: "<<u<<endl;
173                 }
174
175                 if( (isFiltered != filteredSourceSinkMap.end() && filteredSourceSinkMap[sink][property] == uuid) || isFiltered == filteredSourceSinkMap.end())
176                 {
177                         /// FIXME: Set this here just in case a source neglects to:
178                         value->sourceUuid = uuid;
179
180                         sink->propertyChanged(property, value, uuid);
181                 }
182         }
183 }
184
185 std::list<std::string> Core::sourcesForProperty(VehicleProperty::Property property)
186 {
187         std::list<std::string> l;
188
189         for(auto itr = mSources.begin(); itr != mSources.end(); itr++)
190         {
191                 AbstractSource* src = *itr;
192
193                 PropertyList s = src->supported();
194
195                 if(ListPlusPlus<VehicleProperty::Property>(&s).contains(property))
196                 {
197                         l.push_back(src->uuid());
198                 }
199         }
200
201         return l;
202 }
203
204 void Core::registerSink(AbstractSink *self)
205 {
206         if(!ListPlusPlus<AbstractSink*>(&mSinks).contains(self))
207         {
208                 mSinks.push_back(self);
209         }
210 }
211
212 void Core::unregisterSink(AbstractSink *self)
213 {
214         if(ListPlusPlus<AbstractSink*>(&mSinks).contains(self))
215         {
216                 ListPlusPlus<AbstractSink*>(&mSinks).removeOne(self);
217         }
218 }
219
220
221 AsyncPropertyReply *Core::getPropertyAsync(AsyncPropertyRequest request)
222 {
223         AsyncPropertyReply * reply = new AsyncPropertyReply(request);
224
225         for(SourceList::iterator itr = mSources.begin(); itr != mSources.end(); itr++)
226         {
227                 AbstractSource* src = (*itr);
228                 PropertyList properties = src->supported();
229                 int supportedOps = src->supportedOperations();
230
231                 bool supportsGet = supportedOps & AbstractSource::Get;
232
233                 if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(request.property) && supportsGet && (request.sourceUuidFilter == "" || request.sourceUuidFilter == src->uuid()))
234                 {
235
236                         src->getPropertyAsync(reply);
237
238                         /** right now the owner of the reply becomes the requestor that called this method.
239                          *  reply will become invalid after the first reply. */
240                         return reply;
241                 }
242         }
243
244         return reply;
245 }
246
247 AsyncRangePropertyReply *Core::getRangePropertyAsync(AsyncRangePropertyRequest request)
248 {
249         AsyncRangePropertyReply * reply = new AsyncRangePropertyReply(request);
250
251         for(SourceList::iterator itr = mSources.begin(); itr != mSources.end(); itr++)
252         {
253                 AbstractSource* src = (*itr);
254                 PropertyList properties = src->supported();
255                 if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(request.property)
256                                 && (src->supportedOperations() & AbstractSource::GetRanged)
257                                 && (request.sourceUuid == "" || request.sourceUuid == src->uuid()))
258                 {
259                         src->getRangePropertyAsync(reply);
260                 }
261         }
262
263         return reply;
264 }
265
266 AsyncPropertyReply * Core::setProperty(AsyncSetPropertyRequest request)
267 {
268         for(SourceList::iterator itr = mSources.begin(); itr != mSources.end(); itr++)
269         {
270                 AbstractSource* src = (*itr);
271                 PropertyList properties = src->supported();
272                 if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(request.property) && src->supportedOperations() & AbstractSource::Set)
273                 {
274                         return src->setProperty(request);
275                 }
276         }
277
278         DebugOut(0)<<"Error: setProperty opration failed"<<endl;
279         return NULL;
280 }
281
282 void Core::subscribeToProperty(VehicleProperty::Property property, AbstractSink* self)
283 {
284         DebugOut(1)<<"Subscribing to: "<<property<<endl;
285
286         if(propertySinkMap.find(property) == propertySinkMap.end())
287         {
288                 propertySinkMap[property] = SinkList();
289         }
290
291         SinkList list = propertySinkMap[property];
292
293         if(!ListPlusPlus<AbstractSink*>(&list).contains(self))
294         {
295                 propertySinkMap[property].push_back(self);
296         }
297
298         for(SourceList::iterator itr = mSources.begin(); itr != mSources.end(); itr++)
299         {
300                 AbstractSource* src = (*itr);
301                 PropertyList properties = src->supported();
302                 if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(property))
303                 {
304                         src->subscribeToPropertyChanges(property);
305                 }
306         }
307
308 }
309
310 void Core::subscribeToProperty(VehicleProperty::Property property, string sourceUuidFilter, AbstractSink *sink)
311 {
312         if(filteredSourceSinkMap.find(sink) == filteredSourceSinkMap.end() && sourceUuidFilter != "")
313         {
314                 std::map<VehicleProperty::Property, std::string> propertyFilter;
315                 propertyFilter[property] = sourceUuidFilter;
316                 filteredSourceSinkMap[sink] = propertyFilter;
317         }
318
319         subscribeToProperty(property,sink);
320 }
321
322 void Core::subscribeToProperty(VehicleProperty::Property, string sourceUuidFilter, Zone::Type zoneFilter, AbstractSink *self)
323 {
324
325 }
326
327 void Core::unsubscribeToProperty(VehicleProperty::Property property, AbstractSink* self)
328 {
329         if(propertySinkMap.find(property) == propertySinkMap.end())
330         {
331                 DebugOut(1)<<__FUNCTION__<<" property not subscribed to: "<<property<<endl;
332                 return; 
333         }
334                 
335         ListPlusPlus<AbstractSink*>(&propertySinkMap[property]).removeOne(self);
336
337         if( filteredSourceSinkMap.find(self) != filteredSourceSinkMap.end())
338         {
339                 filteredSourceSinkMap.erase(self);
340         }
341
342         /// Now we check to see if this is the last subscriber
343         if(propertySinkMap.find(property) == propertySinkMap.end())
344         {
345                 for(SourceList::iterator itr = mSources.begin(); itr != mSources.end(); itr++)
346                 {
347                         AbstractSource* src = (*itr);
348                         PropertyList properties = src->supported();
349
350                         if(ListPlusPlus<VehicleProperty::Property>(&properties).contains(property))
351                         {
352                                 src->unsubscribeToPropertyChanges(property);
353                         }
354                 }
355         }
356 }
357
358 PropertyInfo Core::getPropertyInfo(VehicleProperty::Property property, string sourceUuid)
359 {
360         for(auto itr = mSources.begin(); itr != mSources.end(); itr++)
361         {
362                 AbstractSource* src = *itr;
363
364                 if(src->uuid() == sourceUuid)
365                 {
366                         return src->getPropertyInfo(property);
367                 }
368         }
369
370         return PropertyInfo::invalid();
371 }
372
373 std::list<string> Core::getSourcesForProperty(VehicleProperty::Property property)
374 {
375         std::list<std::string> list;
376
377         for(auto itr = mSources.begin(); itr != mSources.end(); itr++)
378         {
379                 AbstractSource* src = *itr;
380
381                 PropertyList supportedProperties = src->supported();
382
383                 if(ListPlusPlus<VehicleProperty::Property>(&supportedProperties).contains(property))
384                 {
385                         list.push_back(src->uuid());
386                 }
387         }
388
389         return list;
390 }
391