2 * Copyright (C) 2012, GENIVI Alliance, Inc.
3 * Copyright (C) 2012, BMW AG
5 * This file is part of GENIVI Project AudioManager.
7 * Contributions are licensed to the GENIVI Alliance under one or more
8 * Contribution License Agreements.
11 * This Source Code Form is subject to the terms of the
12 * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
13 * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
16 * \author Christian Mueller, christian.ei.mueller@bmw.de BMW 2011,2012
19 * For further information see http://www.genivi.org/.
23 #include "CAmRouter.h"
28 #include "CAmDatabaseHandler.h"
29 #include "CAmControlSender.h"
33 CAmRouter::CAmRouter(CAmDatabaseHandler* iDatabaseHandler, CAmControlSender* iSender) :
34 mpDatabaseHandler(iDatabaseHandler), //
35 mpControlSender(iSender)
37 assert(mpDatabaseHandler);
38 assert(mpControlSender);
42 * returns the best route between a source and a sink
43 * @param onlyfree if true only free gateways are used
46 * @param returnList this list contains a set of routes
47 * @return E_OK in case of success
49 am_Error_e CAmRouter::getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s> & returnList)
52 //first find out in which domains the source and sink are
53 am_domainID_t sourceDomainID;
54 am_domainID_t sinkDomainID;
55 if (mpDatabaseHandler->getDomainOfSource(sourceID, sourceDomainID) != E_OK)
56 return (E_NON_EXISTENT);
57 if (mpDatabaseHandler->getDomainOfSink(sinkID, sinkDomainID) != E_OK)
58 return (E_NON_EXISTENT);
60 if (sourceDomainID == sinkDomainID) //shortcut if the domains are the same...
62 //first get the list of possible connection formats
63 std::vector<am_ConnectionFormat_e> listFormats, listPriorityConnectionFormats;
64 listPossibleConnectionFormats(sourceID, sinkID, listFormats);
68 route.sinkID = sinkID;
69 route.sourceID = sourceID;
72 //get the prio of the Controller:
73 mpControlSender->getConnectionFormatChoice(sourceID, sinkID, route, listFormats, listPriorityConnectionFormats);
75 //no possible connection, so no route ! But we report OK since there is no fault ...
76 if (listPriorityConnectionFormats.empty())
79 //return the first item as route:
80 am_RoutingElement_s routingElement;
81 routingElement.sourceID = sourceID;
82 routingElement.sinkID = sinkID;
83 routingElement.connectionFormat = listPriorityConnectionFormats[0];
84 routingElement.domainID = sourceDomainID;
87 am_Route_s actualRoute;
88 actualRoute.route.push_back(routingElement);
89 actualRoute.sourceID = sourceID;
90 actualRoute.sinkID = sinkID;
92 //push it to the return list - we are done here ...
93 returnList.push_back(actualRoute);
97 CAmRoutingTree routingtree(sourceDomainID); //Build up a Tree from the Source_Domain to every other domain.
98 std::vector<CAmRoutingTreeItem*> flattree; //This list is the flat tree
99 std::vector<CAmRoutingTreeItem*> matchtree;
100 std::vector<am_gatewayID_t> listGatewayID; //holds all gateway ids of the route
101 am_RoutingElement_s routingElement;
102 am_Route_s actualRoute; //holds the actual Route
103 am_sourceID_t lastSource = 0;
105 mpDatabaseHandler->getRoutingTree(onlyfree, routingtree, flattree); //Build up the tree out of the database as
107 //we go through the returned flattree and look for our sink, after that flattree holds only treeItems that match
108 std::vector<CAmRoutingTreeItem*>::iterator iterator = flattree.begin();
109 for (; iterator != flattree.end(); ++iterator)
111 if ((*iterator)->returnDomainID() == sinkDomainID)
113 matchtree.push_back(*iterator);
117 //No we need to trace back the routes for each entry in matchtree
118 iterator = matchtree.begin();
119 for (; iterator != matchtree.end(); ++iterator)
121 std::vector<am_RoutingElement_s> actualRoutingElement; //intermediate list of current routing pairs
122 //getting the route for the actual item
123 routingtree.getRoute(*iterator, listGatewayID); //This gives only the Gateway IDs we need more
125 //go throught the gatewayids and get more information
126 std::vector<am_gatewayID_t>::iterator gatewayIterator = listGatewayID.begin();
127 for (; gatewayIterator != listGatewayID.end(); ++gatewayIterator)
129 am_Gateway_s gatewayData;
130 if (mpDatabaseHandler->getGatewayInfoDB(*gatewayIterator, gatewayData) != E_OK)
133 //at the beginning of the route, we connect first the source to the first gateway
134 if (gatewayIterator == listGatewayID.begin())
136 routingElement.sourceID = sourceID;
137 routingElement.domainID = sourceDomainID;
141 routingElement.sourceID = lastSource;
142 routingElement.domainID = gatewayData.domainSinkID;
144 routingElement.sinkID = gatewayData.sinkID;
145 actualRoutingElement.push_back(routingElement);
146 lastSource = gatewayData.sourceID;
148 //at the end of the route, connect to the sink !
149 routingElement.sourceID = lastSource;
150 routingElement.sinkID = sinkID;
151 routingElement.domainID = sinkDomainID;
152 actualRoutingElement.push_back(routingElement);
154 //So now we got the route, what is missing are the connectionFormats...
156 //Step through the routes and try to use always the best connectionFormat
157 std::vector<am_RoutingElement_s>::iterator routingInterator = actualRoutingElement.begin();
158 gatewayIterator = listGatewayID.begin();
159 if (findBestWay(sinkID, sourceID, actualRoutingElement, routingInterator, gatewayIterator) != E_OK)
164 //add the route to the list of routes...
165 actualRoute.sourceID = sourceID;
166 actualRoute.sinkID = sinkID;
167 actualRoute.route = actualRoutingElement;
168 returnList.push_back(actualRoute);
173 void CAmRouter::listPossibleConnectionFormats(const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_ConnectionFormat_e>& listFormats) const
175 std::vector<am_ConnectionFormat_e> listSourceFormats;
176 std::vector<am_ConnectionFormat_e> listSinkFormats;
177 mpDatabaseHandler->getListSinkConnectionFormats(sinkID, listSinkFormats);
178 mpDatabaseHandler->getListSourceConnectionFormats(sourceID, listSourceFormats);
179 std::sort(listSinkFormats.begin(), listSinkFormats.end()); //todo: this might be not needed if we use strictly sorted input
180 std::sort(listSourceFormats.begin(), listSourceFormats.end()); //todo: this might be not needed if we use strictly sorted input
181 std::insert_iterator<std::vector<am_ConnectionFormat_e> > inserter(listFormats, listFormats.begin());
182 set_intersection(listSourceFormats.begin(), listSourceFormats.end(), listSinkFormats.begin(), listSinkFormats.end(), inserter);
185 am_Error_e CAmRouter::findBestWay(am_sinkID_t sinkID, am_sourceID_t sourceID, std::vector<am_RoutingElement_s> & listRoute, std::vector<am_RoutingElement_s>::iterator routeIterator, std::vector<am_gatewayID_t>::iterator gatewayIterator)
187 am_Error_e returnError = E_NOT_POSSIBLE;
188 std::vector<am_ConnectionFormat_e> listConnectionFormats;
189 std::vector<am_ConnectionFormat_e> listMergeConnectionFormats;
190 std::vector<am_ConnectionFormat_e> listPriorityConnectionFormats;
191 std::vector<am_RoutingElement_s>::iterator nextIterator = routeIterator + 1;
192 //get best connection format
193 listPossibleConnectionFormats(routeIterator->sourceID, routeIterator->sinkID, listConnectionFormats);
195 //if we have not just started, we need to take care about the gateways...
196 if (routeIterator != listRoute.begin())
198 //since we have to deal with Gateways, there are restrictions what connectionFormat we can take. So we need to take the subset of connections that are restricted:
199 std::vector<am_ConnectionFormat_e> listRestrictedConnectionFormats;
200 std::insert_iterator<std::vector<am_ConnectionFormat_e> > inserter(listMergeConnectionFormats, listMergeConnectionFormats.begin());
201 std::vector<am_RoutingElement_s>::iterator tempIterator(routeIterator);
203 listRestrictedOutputFormatsGateways(*gatewayIterator, (tempIterator)->connectionFormat, listRestrictedConnectionFormats);
204 std::sort(listRestrictedConnectionFormats.begin(), listRestrictedConnectionFormats.end()); //todo: this might be not needed if we use strictly sorted input
205 set_intersection(listConnectionFormats.begin(), listConnectionFormats.end(), listRestrictedConnectionFormats.begin(), listRestrictedConnectionFormats.end(), inserter);
210 listMergeConnectionFormats = listConnectionFormats;
214 route.sinkID = sinkID;
215 route.sourceID = sourceID;
216 route.route = listRoute;
218 //let the controller decide:
219 mpControlSender->getConnectionFormatChoice(routeIterator->sourceID, routeIterator->sinkID, route, listMergeConnectionFormats, listPriorityConnectionFormats);
221 //we have the list sorted after prios - now we try one after the other with the next part of the route
222 std::vector<am_ConnectionFormat_e>::iterator connectionFormatIterator = listPriorityConnectionFormats.begin();
224 //here we need to check if we are at the end and stop
225 if (nextIterator == listRoute.end())
227 if (!listPriorityConnectionFormats.empty())
229 routeIterator->connectionFormat = listPriorityConnectionFormats.front();
233 return (E_NOT_POSSIBLE);
236 for (; connectionFormatIterator != listPriorityConnectionFormats.end(); ++connectionFormatIterator)
238 routeIterator->connectionFormat = *connectionFormatIterator;
239 if ((returnError = findBestWay(sinkID, sourceID, listRoute, nextIterator, gatewayIterator)) == E_OK)
245 return (returnError);
248 void CAmRouter::listRestrictedOutputFormatsGateways(const am_gatewayID_t gatewayID, const am_ConnectionFormat_e sinkConnectionFormat, std::vector<am_ConnectionFormat_e> & listFormats) const
251 am_Gateway_s gatewayData;
252 mpDatabaseHandler->getGatewayInfoDB(gatewayID, gatewayData);
253 std::vector<am_ConnectionFormat_e>::const_iterator rowSinkIterator = gatewayData.listSinkFormats.begin();
254 std::vector<bool>::const_iterator matrixIterator = gatewayData.convertionMatrix.begin();
256 //find the row number of the sink
257 rowSinkIterator = find(gatewayData.listSinkFormats.begin(), gatewayData.listSinkFormats.end(), sinkConnectionFormat);
258 int rowNumberSink = rowSinkIterator - gatewayData.listSinkFormats.begin();
260 //go through the convertionMatrix and find out if the conversion is possible, if yes, add connectionFormat ...
261 std::advance(matrixIterator, rowNumberSink);
263 //iterate line-wise through the matrix and add more formats
268 listFormats.push_back(gatewayData.listSourceFormats.at((matrixIterator - gatewayData.convertionMatrix.begin()) / gatewayData.listSinkFormats.size()));
270 std::advance(matrixIterator, gatewayData.listSinkFormats.size());
271 } while (gatewayData.convertionMatrix.end() - matrixIterator > 0);
274 CAmRouter::~CAmRouter()
278 CAmRoutingTreeItem::CAmRoutingTreeItem(const am_domainID_t domainID, const am_gatewayID_t gatewayID, CAmRoutingTreeItem *parent) :
279 mDomainID(domainID), //
280 mGatewayID(gatewayID), //
283 assert(mDomainID!=0);
286 void CAmRoutingTreeItem::appendChild(CAmRoutingTreeItem *newChild)
289 mListChildItems.push_back(newChild);
292 void CAmRoutingTreeItem::returnChildItems(std::vector<CAmRoutingTreeItem*> listChildItems)
294 listChildItems = mListChildItems;
297 am_domainID_t CAmRoutingTreeItem::returnDomainID() const
302 am_gatewayID_t CAmRoutingTreeItem::returnGatewayID() const
307 CAmRoutingTreeItem* CAmRoutingTreeItem::returnParent() const
309 return (mpParentItem);
312 CAmRoutingTreeItem::~CAmRoutingTreeItem()
316 CAmRoutingTree::CAmRoutingTree(const am_domainID_t rootDomainID) :
317 mRootItem(CAmRoutingTreeItem(rootDomainID))
319 assert(rootDomainID!=0);
322 CAmRoutingTreeItem *CAmRoutingTree::insertItem(const am_domainID_t domainID, const am_gatewayID_t gatewayID, CAmRoutingTreeItem *parent)
324 CAmRoutingTreeItem *newTree = new CAmRoutingTreeItem(domainID, gatewayID, parent);
325 parent->appendChild(newTree);
326 mListChild.push_back(newTree);
330 void CAmRoutingTree::getRoute(CAmRoutingTreeItem *targetItem, std::vector<am_gatewayID_t>& listGateways)
332 listGateways.clear();
333 CAmRoutingTreeItem *parentItem = targetItem;
334 while (parentItem != &mRootItem)
336 listGateways.push_back(parentItem->returnGatewayID());
337 parentItem = parentItem->returnParent();
339 std::reverse(listGateways.begin(), listGateways.end());
342 am_domainID_t CAmRoutingTree::returnRootDomainID() const
344 return (mRootItem.returnDomainID());
347 CAmRoutingTreeItem *CAmRoutingTree::returnRootItem()
352 CAmRoutingTree::~CAmRoutingTree()
354 std::vector<CAmRoutingTreeItem*>::iterator it = mListChild.begin();
355 for (; it != mListChild.end(); ++it)