2 * Copyright (C) 2012, BMW AG
4 * This file is part of GENIVI Project AudioManager.
6 * Contributions are licensed to the GENIVI Alliance under one or more
7 * Contribution License Agreements.
10 * This Source Code Form is subject to the terms of the
11 * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
12 * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 * \author Christian Mueller, christian.ei.mueller@bmw.de BMW 2011,2012
18 * For further information see http://www.genivi.org/.
22 #include "CAmRouter.h"
27 #include "CAmDatabaseHandler.h"
28 #include "CAmControlSender.h"
32 CAmRouter::CAmRouter(CAmDatabaseHandler* iDatabaseHandler, CAmControlSender* iSender) :
33 mpDatabaseHandler(iDatabaseHandler), //
34 mpControlSender(iSender)
36 assert(mpDatabaseHandler);
37 assert(mpControlSender);
41 * returns the best route between a source and a sink
42 * @param onlyfree if true only free gateways are used
45 * @param returnList this list contains a set of routes
46 * @return E_OK in case of success
48 am_Error_e CAmRouter::getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s> & returnList)
51 //first find out in which domains the source and sink are
52 am_domainID_t sourceDomainID;
53 am_domainID_t sinkDomainID;
54 if (mpDatabaseHandler->getDomainOfSource(sourceID, sourceDomainID) != E_OK)
55 return (E_NON_EXISTENT);
56 if (mpDatabaseHandler->getDomainOfSink(sinkID, sinkDomainID) != E_OK)
57 return (E_NON_EXISTENT);
59 if (sourceDomainID == sinkDomainID) //shortcut if the domains are the same...
61 //first get the list of possible connection formats
62 std::vector<am_ConnectionFormat_e> listFormats, listPriorityConnectionFormats;
63 listPossibleConnectionFormats(sourceID, sinkID, listFormats);
67 route.sinkID = sinkID;
68 route.sourceID = sourceID;
71 //get the prio of the Controller:
72 mpControlSender->getConnectionFormatChoice(sourceID, sinkID, route, listFormats, listPriorityConnectionFormats);
74 //no possible connection, so no route ! But we report OK since there is no fault ...
75 if (listPriorityConnectionFormats.empty())
78 //return the first item as route:
79 am_RoutingElement_s routingElement;
80 routingElement.sourceID = sourceID;
81 routingElement.sinkID = sinkID;
82 routingElement.connectionFormat = listPriorityConnectionFormats[0];
83 routingElement.domainID = sourceDomainID;
86 am_Route_s actualRoute;
87 actualRoute.route.push_back(routingElement);
88 actualRoute.sourceID = sourceID;
89 actualRoute.sinkID = sinkID;
91 //push it to the return list - we are done here ...
92 returnList.push_back(actualRoute);
96 CAmRoutingTree routingtree(sourceDomainID); //Build up a Tree from the Source_Domain to every other domain.
97 std::vector<CAmRoutingTreeItem*> flattree; //This list is the flat tree
98 std::vector<CAmRoutingTreeItem*> matchtree;
99 std::vector<am_gatewayID_t> listGatewayID; //holds all gateway ids of the route
100 am_RoutingElement_s routingElement;
101 am_Route_s actualRoute; //holds the actual Route
102 am_sourceID_t lastSource = 0;
104 mpDatabaseHandler->getRoutingTree(onlyfree, routingtree, flattree); //Build up the tree out of the database as
106 //we go through the returned flattree and look for our sink, after that flattree holds only treeItems that match
107 std::vector<CAmRoutingTreeItem*>::iterator iterator = flattree.begin();
108 for (; iterator != flattree.end(); ++iterator)
110 if ((*iterator)->returnDomainID() == sinkDomainID)
112 matchtree.push_back(*iterator);
116 //No we need to trace back the routes for each entry in matchtree
117 iterator = matchtree.begin();
118 for (; iterator != matchtree.end(); ++iterator)
120 std::vector<am_RoutingElement_s> actualRoutingElement; //intermediate list of current routing pairs
121 //getting the route for the actual item
122 routingtree.getRoute(*iterator, listGatewayID); //This gives only the Gateway IDs we need more
124 //go throught the gatewayids and get more information
125 std::vector<am_gatewayID_t>::iterator gatewayIterator = listGatewayID.begin();
126 for (; gatewayIterator != listGatewayID.end(); ++gatewayIterator)
128 am_Gateway_s gatewayData;
129 if (mpDatabaseHandler->getGatewayInfoDB(*gatewayIterator, gatewayData) != E_OK)
132 //at the beginning of the route, we connect first the source to the first gateway
133 if (gatewayIterator == listGatewayID.begin())
135 routingElement.sourceID = sourceID;
136 routingElement.domainID = sourceDomainID;
140 routingElement.sourceID = lastSource;
141 routingElement.domainID = gatewayData.domainSinkID;
143 routingElement.sinkID = gatewayData.sinkID;
144 actualRoutingElement.push_back(routingElement);
145 lastSource = gatewayData.sourceID;
147 //at the end of the route, connect to the sink !
148 routingElement.sourceID = lastSource;
149 routingElement.sinkID = sinkID;
150 routingElement.domainID = sinkDomainID;
151 actualRoutingElement.push_back(routingElement);
153 //So now we got the route, what is missing are the connectionFormats...
155 //Step through the routes and try to use always the best connectionFormat
156 std::vector<am_RoutingElement_s>::iterator routingInterator = actualRoutingElement.begin();
157 gatewayIterator = listGatewayID.begin();
158 if (findBestWay(sinkID, sourceID, actualRoutingElement, routingInterator, gatewayIterator) != E_OK)
163 //add the route to the list of routes...
164 actualRoute.sourceID = sourceID;
165 actualRoute.sinkID = sinkID;
166 actualRoute.route = actualRoutingElement;
167 returnList.push_back(actualRoute);
172 void CAmRouter::listPossibleConnectionFormats(const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_ConnectionFormat_e>& listFormats) const
174 std::vector<am_ConnectionFormat_e> listSourceFormats;
175 std::vector<am_ConnectionFormat_e> listSinkFormats;
176 mpDatabaseHandler->getListSinkConnectionFormats(sinkID, listSinkFormats);
177 mpDatabaseHandler->getListSourceConnectionFormats(sourceID, listSourceFormats);
178 std::sort(listSinkFormats.begin(), listSinkFormats.end()); //todo: this might be not needed if we use strictly sorted input
179 std::sort(listSourceFormats.begin(), listSourceFormats.end()); //todo: this might be not needed if we use strictly sorted input
180 std::insert_iterator<std::vector<am_ConnectionFormat_e> > inserter(listFormats, listFormats.begin());
181 set_intersection(listSourceFormats.begin(), listSourceFormats.end(), listSinkFormats.begin(), listSinkFormats.end(), inserter);
184 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)
186 am_Error_e returnError = E_NOT_POSSIBLE;
187 std::vector<am_ConnectionFormat_e> listConnectionFormats;
188 std::vector<am_ConnectionFormat_e> listMergeConnectionFormats;
189 std::vector<am_ConnectionFormat_e> listPriorityConnectionFormats;
190 std::vector<am_RoutingElement_s>::iterator nextIterator = routeIterator + 1;
191 //get best connection format
192 listPossibleConnectionFormats(routeIterator->sourceID, routeIterator->sinkID, listConnectionFormats);
194 //if we have not just started, we need to take care about the gateways...
195 if (routeIterator != listRoute.begin())
197 //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:
198 std::vector<am_ConnectionFormat_e> listRestrictedConnectionFormats;
199 std::insert_iterator<std::vector<am_ConnectionFormat_e> > inserter(listMergeConnectionFormats, listMergeConnectionFormats.begin());
200 std::vector<am_RoutingElement_s>::iterator tempIterator(routeIterator);
202 listRestrictedOutputFormatsGateways(*gatewayIterator, (tempIterator)->connectionFormat, listRestrictedConnectionFormats);
203 std::sort(listRestrictedConnectionFormats.begin(), listRestrictedConnectionFormats.end()); //todo: this might be not needed if we use strictly sorted input
204 set_intersection(listConnectionFormats.begin(), listConnectionFormats.end(), listRestrictedConnectionFormats.begin(), listRestrictedConnectionFormats.end(), inserter);
209 listMergeConnectionFormats = listConnectionFormats;
213 route.sinkID = sinkID;
214 route.sourceID = sourceID;
215 route.route = listRoute;
217 //let the controller decide:
218 mpControlSender->getConnectionFormatChoice(routeIterator->sourceID, routeIterator->sinkID, route, listMergeConnectionFormats, listPriorityConnectionFormats);
220 //we have the list sorted after prios - now we try one after the other with the next part of the route
221 std::vector<am_ConnectionFormat_e>::iterator connectionFormatIterator = listPriorityConnectionFormats.begin();
223 //here we need to check if we are at the end and stop
224 if (nextIterator == listRoute.end())
226 if (!listPriorityConnectionFormats.empty())
228 routeIterator->connectionFormat = listPriorityConnectionFormats.front();
232 return (E_NOT_POSSIBLE);
235 for (; connectionFormatIterator != listPriorityConnectionFormats.end(); ++connectionFormatIterator)
237 routeIterator->connectionFormat = *connectionFormatIterator;
238 if ((returnError = findBestWay(sinkID, sourceID, listRoute, nextIterator, gatewayIterator)) == E_OK)
244 return (returnError);
247 void CAmRouter::listRestrictedOutputFormatsGateways(const am_gatewayID_t gatewayID, const am_ConnectionFormat_e sinkConnectionFormat, std::vector<am_ConnectionFormat_e> & listFormats) const
250 am_Gateway_s gatewayData;
251 mpDatabaseHandler->getGatewayInfoDB(gatewayID, gatewayData);
252 std::vector<am_ConnectionFormat_e>::const_iterator rowSinkIterator = gatewayData.listSinkFormats.begin();
253 std::vector<bool>::const_iterator matrixIterator = gatewayData.convertionMatrix.begin();
255 //find the row number of the sink
256 rowSinkIterator = find(gatewayData.listSinkFormats.begin(), gatewayData.listSinkFormats.end(), sinkConnectionFormat);
257 int rowNumberSink = rowSinkIterator - gatewayData.listSinkFormats.begin();
259 //go through the convertionMatrix and find out if the conversion is possible, if yes, add connectionFormat ...
260 std::advance(matrixIterator, rowNumberSink);
262 //iterate line-wise through the matrix and add more formats
267 listFormats.push_back(gatewayData.listSourceFormats.at((matrixIterator - gatewayData.convertionMatrix.begin()) / gatewayData.listSinkFormats.size()));
269 std::advance(matrixIterator, gatewayData.listSinkFormats.size());
270 } while (gatewayData.convertionMatrix.end() - matrixIterator > 0);
273 CAmRouter::~CAmRouter()
277 CAmRoutingTreeItem::CAmRoutingTreeItem(const am_domainID_t domainID, const am_gatewayID_t gatewayID, CAmRoutingTreeItem *parent) :
278 mDomainID(domainID), //
279 mGatewayID(gatewayID), //
282 assert(mDomainID!=0);
285 void CAmRoutingTreeItem::appendChild(CAmRoutingTreeItem *newChild)
288 mListChildItems.push_back(newChild);
291 void CAmRoutingTreeItem::returnChildItems(std::vector<CAmRoutingTreeItem*> listChildItems)
293 listChildItems = mListChildItems;
296 am_domainID_t CAmRoutingTreeItem::returnDomainID() const
301 am_gatewayID_t CAmRoutingTreeItem::returnGatewayID() const
306 CAmRoutingTreeItem* CAmRoutingTreeItem::returnParent() const
308 return (mpParentItem);
311 CAmRoutingTreeItem::~CAmRoutingTreeItem()
315 CAmRoutingTree::CAmRoutingTree(const am_domainID_t rootDomainID) :
316 mRootItem(CAmRoutingTreeItem(rootDomainID))
318 assert(rootDomainID!=0);
321 CAmRoutingTreeItem *CAmRoutingTree::insertItem(const am_domainID_t domainID, const am_gatewayID_t gatewayID, CAmRoutingTreeItem *parent)
323 CAmRoutingTreeItem *newTree = new CAmRoutingTreeItem(domainID, gatewayID, parent);
324 parent->appendChild(newTree);
325 mListChild.push_back(newTree);
329 void CAmRoutingTree::getRoute(CAmRoutingTreeItem *targetItem, std::vector<am_gatewayID_t>& listGateways)
331 listGateways.clear();
332 CAmRoutingTreeItem *parentItem = targetItem;
333 while (parentItem != &mRootItem)
335 listGateways.push_back(parentItem->returnGatewayID());
336 parentItem = parentItem->returnParent();
338 std::reverse(listGateways.begin(), listGateways.end());
341 am_domainID_t CAmRoutingTree::returnRootDomainID() const
343 return (mRootItem.returnDomainID());
346 CAmRoutingTreeItem *CAmRoutingTree::returnRootItem()
351 CAmRoutingTree::~CAmRoutingTree()
353 std::vector<CAmRoutingTreeItem*>::iterator it = mListChild.begin();
354 for (; it != mListChild.end(); ++it)