summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksandar Donchev <Aleksander.Donchev@partner.bmw.de>2017-01-23 15:18:21 +0100
committerChristian Linke <christian.linke@bmw.de>2017-02-20 08:49:44 -0800
commit277a638bf1d27ba6c3da37ff82d2fd06e718e7ca (patch)
tree8a1e66b915bea8fca798afbe6cd8ef232612dad9
parent17c439ae25beec19fba090faa360d6ef04336a4c (diff)
downloadaudiomanager-277a638bf1d27ba6c3da37ff82d2fd06e718e7ca.tar.gz
* Max count of the returned routes and max allowed domain cycles
Signed-off-by: Christian Linke <christian.linke@bmw.de>
-rw-r--r--AudioManagerCore/include/CAmGraph.h129
-rw-r--r--AudioManagerCore/include/CAmRouter.h172
-rw-r--r--AudioManagerCore/src/CAmRouter.cpp518
-rw-r--r--AudioManagerCore/test/AmRouterMapTest/CAmRouterMapTest.cpp271
-rw-r--r--AudioManagerCore/test/AmRouterMapTest/CAmRouterMapTest.h10
5 files changed, 723 insertions, 377 deletions
diff --git a/AudioManagerCore/include/CAmGraph.h b/AudioManagerCore/include/CAmGraph.h
index ff4a09c..a27d512 100644
--- a/AudioManagerCore/include/CAmGraph.h
+++ b/AudioManagerCore/include/CAmGraph.h
@@ -89,6 +89,7 @@ namespace am
* Setters and getters.
*/
NodeData & getData() { return mData; }
+ const NodeData & getData() const { return mData; }
uint16_t getIndex() const { return mIndex; }
void setIndex(uint16_t index) { mIndex = index; }
};
@@ -120,13 +121,13 @@ namespace am
typedef typename std::vector<CAmNode<T>*> CAmListNodePtrs;
typedef typename std::list<CAmVertex<T,V>> CAmListVertices;
typedef typename std::list<CAmVertex<T,V>>::iterator CAmListVerticesItr;
- typedef typename std::list<CAmVertex<T,V>>::const_iterator CAmListVerticesItrConst;
- typedef typename std::list<CAmListVertices> CAmNodesAdjList;
- typedef typename std::list<CAmListVertices>::iterator CAmNodesAdjListItr;
- typedef typename std::list<CAmListVertices>::const_iterator CAmNodesAdjListItrConst;
- typedef typename std::list<CAmNode<T>> CAmListNodes;
- typedef typename std::list<CAmNode<T>>::iterator CAmListNodesItr;
- typedef typename std::list<CAmNode<T>>::const_iterator CAmListNodesItrConst;
+ typedef typename std::list<CAmVertex<T,V>>::const_iterator CAmListVerticesItrConst;
+ typedef typename std::list<CAmListVertices> CAmNodesAdjList;
+ typedef typename std::list<CAmListVertices>::iterator CAmNodesAdjListItr;
+ typedef typename std::list<CAmListVertices>::const_iterator CAmNodesAdjListItrConst;
+ typedef typename std::list<CAmNode<T>> CAmListNodes;
+ typedef typename std::list<CAmNode<T>>::iterator CAmListNodesItr;
+ typedef typename std::list<CAmNode<T>>::const_iterator CAmListNodesItrConst;
typedef typename std::vector<CAmNode<T>*> CAmNodeReferenceList;
typedef typename std::vector<CAmListVertices*> CAmVertexReferenceList;
@@ -136,6 +137,24 @@ namespace am
CAmVertexReferenceList mPointersAdjList; //!< CAmVertexReferenceList vector with pointers to vertices for direct access
bool mIsCyclic; //!< bool the graph has cycles or not
+ struct IterateThroughAllNodesDelegate
+ {
+ CAmNode<T> * source;
+ CAmNode<T> * destination;
+ CAmNodeReferenceList visited;
+ std::function<bool(const CAmNode<T> * )> shouldVisitNode;
+ std::function<void(const CAmNode<T> *)> willVisitNode;
+ std::function<void(const CAmNode<T> *)> didVisitNode;
+ std::function<void(const CAmNodeReferenceList & path)> didFindPath;
+ };
+
+ struct VisitNodeDelegate
+ {
+ CAmNode<T> * source;
+ CAmNode<T> * destination;
+ std::function<void(const am_GraphPathPosition_e, CAmNode<T> &)> visitedNode;
+ };
+
/**
* Updates the node indexes after adding or removing nodes.
*
@@ -162,7 +181,7 @@ namespace am
typedef uint16_t vertex_t;
typedef uint16_t weight_t;
- void findShortestsPathsFromNode(const CAmNode<T> & node, std::vector<weight_t> &minDistance, std::vector<CAmNode<T> *> &previous)
+ void findShortestPathsFromNode(const CAmNode<T> & node, std::vector<weight_t> &minDistance, std::vector<CAmNode<T> *> &previous)
{
typename CAmListVertices::const_iterator nIter;
CAmListVertices * neighbors;
@@ -256,32 +275,40 @@ namespace am
}
/**
- * Generates list with all possible paths to given destination node after findShortestsPathsFromNode has been called.
- * Finding paths is observed through the callback. The caller is informed after a new path has been found.
+ * Iterate through the nodes and generate all paths to given node.
*
* @param dst end node.
* @param visited vector with current path.
- * @param cb callback which is mostly used for constructing.
+ * @param delegate enumeration delegate.
*/
- void goThroughAllPaths(const CAmNode<T> & dst, std::vector<CAmNode<T>*> & visited, std::function<void(const CAmNodeReferenceList & path)> cb)
+ void findAllPaths(IterateThroughAllNodesDelegate & delegate)
{
- CAmListVertices * nodes = mPointersAdjList[visited.back()->getIndex()];
+ CAmListVertices * nodes = mPointersAdjList[delegate.visited.back()->getIndex()];
CAmListVerticesItrConst vItr(nodes->begin());
+
+ CAmVertex<T,V> * pNextVertex;
+ CAmNode<T> * pNextNode;
for (; vItr != nodes->end(); ++vItr)
{
- const CAmVertex<T,V> & vertex = (*vItr);
- if(vertex.getNode()->getStatus()!=GES_NOT_VISITED)
+ pNextVertex = (CAmVertex<T,V> *)&(*vItr);
+ pNextNode = pNextVertex->getNode();
+ if(
+ pNextNode->getStatus()!=GES_NOT_VISITED ||
+ !delegate.shouldVisitNode(pNextNode)
+ )
continue;
- if (vertex.getNode()==&dst)
+ if (pNextNode==delegate.destination)
{
- vertex.getNode()->setStatus(GES_IN_PROGRESS);
- visited.push_back(vertex.getNode());
+ delegate.willVisitNode(pNextNode);
+ pNextNode->setStatus(GES_IN_PROGRESS);
+ delegate.visited.push_back(pNextNode);
//notify observer
- cb(visited);
+ delegate.didFindPath(delegate.visited);
//remove last node from the list
- auto last = visited.end()-1;
- visited.erase(last);
- vertex.getNode()->setStatus(GES_NOT_VISITED);
+ auto last = delegate.visited.end()-1;
+ delegate.visited.erase(last);
+ pNextNode->setStatus(GES_NOT_VISITED);
+ delegate.didVisitNode(pNextNode);
break;
}
}
@@ -289,20 +316,28 @@ namespace am
//bfs like loop
for (; vItr != nodes->end(); ++vItr)
{
- const CAmVertex<T,V> & vertex = (*vItr);
- if(vertex.getNode()->getStatus()!=GES_NOT_VISITED||vertex.getNode()==&dst)
+ pNextVertex = (CAmVertex<T,V> *)&(*vItr);
+ pNextNode = pNextVertex->getNode();
+
+ if(pNextNode->getStatus()!=GES_NOT_VISITED ||
+ pNextNode==delegate.destination ||
+ !delegate.shouldVisitNode(pNextNode)
+ )
continue;
- vertex.getNode()->setStatus(GES_IN_PROGRESS);
- visited.push_back(vertex.getNode());
- goThroughAllPaths(dst, visited, cb);
+ delegate.willVisitNode(pNextNode);
+ pNextNode->setStatus(GES_IN_PROGRESS);
+ delegate.visited.push_back(pNextNode);
+ findAllPaths(delegate);
//remove last node from the list
- auto last = visited.end()-1;
- visited.erase(last);
- vertex.getNode()->setStatus(GES_NOT_VISITED);
+ auto last = delegate.visited.end()-1;
+ delegate.visited.erase(last);
+ pNextNode->setStatus(GES_NOT_VISITED);
+ delegate.didVisitNode(pNextNode);
}
}
public:
+
explicit CAmGraph(const std::vector<T> &v):mStoreNodes(), mStoreAdjList(), mPointersNodes(), mPointersAdjList()
{
typedef typename std::vector<T>::const_iterator inItr;
@@ -524,7 +559,7 @@ namespace am
std::vector<weight_t> min_distance;
std::vector<CAmNode<T>*> previous;
- findShortestsPathsFromNode(source, min_distance, previous);
+ findShortestPathsFromNode(source, min_distance, previous);
for(auto it=listTargets.begin(); it!=listTargets.end(); it++)
{
@@ -554,7 +589,7 @@ namespace am
return;
std::vector<weight_t> min_distance;
std::vector<CAmNode<T>*> previous;
- findShortestsPathsFromNode(source, min_distance, previous);
+ findShortestPathsFromNode(source, min_distance, previous);
constructShortestPathTo(destination, previous, resultPath);
}
@@ -576,7 +611,7 @@ namespace am
std::vector<weight_t> min_distance;
std::vector<CAmNode<T>*> previous;
- findShortestsPathsFromNode(source, min_distance, previous);
+ findShortestPathsFromNode(source, min_distance, previous);
for(auto it=listTargets.begin(); it!=listTargets.end(); it++)
{
@@ -603,7 +638,7 @@ namespace am
std::vector<weight_t> min_distance;
std::vector<CAmNode<T>*> previous;
- findShortestsPathsFromNode(source, min_distance, previous);
+ findShortestPathsFromNode(source, min_distance, previous);
constructShortestPathTo(destination, previous, cb);
}
@@ -613,15 +648,29 @@ namespace am
*
* @param src start node.
* @param dst destination node.
- * @param cb callabck.
+ * @param cbShouldVisitNode ask the delegate if we should proceed with the current node.
+ * @param cbWillVisitNode tell the delegate the current node will be visited.
+ * @param cbDidVisitNode tell the delegate the current node was visited.
+ * @param cbDidFindPath return the path to the delegate.
*/
- void getAllPaths(const CAmNode<T> & src, const CAmNode<T> & dst, std::function<void(const CAmNodeReferenceList & path)> cb)
+ void getAllPaths(CAmNode<T> & src,
+ CAmNode<T> & dst,
+ std::function<bool(const CAmNode<T> * )> cbShouldVisitNode,
+ std::function<void(const CAmNode<T> *)> cbWillVisitNode,
+ std::function<void(const CAmNode<T> *)> cbDidVisitNode,
+ std::function<void(const CAmNodeReferenceList & path)> cbDidFindPath)
{
- CAmNodeReferenceList visited;
- visited.push_back((CAmNode<T>*)&src);
+ IterateThroughAllNodesDelegate delegate;
+ delegate.source = &src;
+ delegate.destination = &dst;
+ delegate.shouldVisitNode = cbShouldVisitNode;
+ delegate.willVisitNode = cbWillVisitNode;
+ delegate.didVisitNode = cbDidVisitNode;
+ delegate.didFindPath = cbDidFindPath;
+ delegate.visited.push_back((CAmNode<T>*)&src);
((CAmNode<T>*)&src)->setStatus(GES_VISITED);
- goThroughAllPaths(dst, visited, cb);
- reset();
+ findAllPaths(delegate);
+ ((CAmNode<T>*)&src)->setStatus(GES_NOT_VISITED);
}
};
diff --git a/AudioManagerCore/include/CAmRouter.h b/AudioManagerCore/include/CAmRouter.h
index 705fb4a..f4955d6 100644
--- a/AudioManagerCore/include/CAmRouter.h
+++ b/AudioManagerCore/include/CAmRouter.h
@@ -38,7 +38,7 @@ namespace am
{
/**
- * Optimal path search between a source and a sink is implemented with a graph which contains nodes - sinks, sources, gateways, converters.
+ * Optimal path search is implemented with graph which contains nodes - sinks, sources, gateways, converters.
* The nodes are identified by sinkID, sourceID, gatewayID, converterID.
* A possible connection between two nodes represents the facts that the nodes can be connected with one or more connectionFormats (Node[id=1] ---> Node[id=2]).
* It is assumption that the two nodes can be connected. The controller itself decides later whether the connection is possible or not.
@@ -48,22 +48,25 @@ namespace am
/**
* Trace on/off.
*/
-#if !defined(ROUTING_BUILD_CONNECTIONS)
- #undef TRACE_GRAPH
-#endif
+#undef TRACE_GRAPH
/**
- * Default behavior is to do the search in one step without connections, which are identified during the search.
- * Alternatively the search can be done in two steps.
+ * Max paths count returned to the controller
*/
-#if !defined(ROUTING_BUILD_CONNECTIONS)
- #undef ROUTING_BUILD_CONNECTIONS
-#endif
-
-#if defined(TRACE_GRAPH)
-#if !defined(ROUTING_BUILD_CONNECTIONS)
-#warning "You should define ROUTING_BUILD_CONNECTIONS in order to be able to see the connections in the trace."
+#ifndef MAX_ROUTING_PATHS
+#define MAX_ROUTING_PATHS 5
#endif
+/**
+ * How many times the routing algorithm should look back into domains.
+ *
+ * 0 - no cycles are allowed
+ * 1 - default is one cycle
+ * ...
+ * UINT_MAX - set this define to UINT_MAX in order to allow cycles.
+ *
+ */
+#ifndef MAX_ALLOWED_DOMAIN_CYCLES
+#define MAX_ALLOWED_DOMAIN_CYCLES 1
#endif
class CAmRouter;
@@ -150,23 +153,17 @@ class CAmControlSender;
*/
class CAmRouter
{
- IAmDatabaseHandler* mpDatabaseHandler; //!< pointer to database handler
- CAmControlSender* mpControlSender; //!< pointer the controlsender - is used to retrieve information for the optimal route
- bool mOnlyFreeConversionNodes; //!< bool flag whether only disconnected elements should be considered or not
- CAmRoutingGraph mRoutingGraph; //!< graph object
- std::map<am_domainID_t,std::vector<CAmRoutingNode*>> mNodeListSources; //!< map with pointers to nodes with sources, used for quick access
- std::map<am_domainID_t,std::vector<CAmRoutingNode*>> mNodeListSinks; //!< map with pointers to nodes with sinks, used for quick access
- std::map<am_domainID_t,std::vector<CAmRoutingNode*>> mNodeListGateways; //!< map with pointers to nodes with gateways, used for quick access
+ IAmDatabaseHandler* mpDatabaseHandler; //!< pointer to database handler
+ CAmControlSender* mpControlSender; //!< pointer the controlsender - is used to retrieve information for the optimal route
+ bool mOnlyFreeConversionNodes; //!< bool flag whether only disconnected elements should be considered or not
+ unsigned mMaxAllowedCycles; //!< max allowed cycles, default is 1
+ unsigned mMaxPathCount; //!< max paths count returned to the controller, default is 5
+ CAmRoutingGraph mRoutingGraph; //!< graph object
+ std::map<am_domainID_t,std::vector<CAmRoutingNode*>> mNodeListSources; //!< map with pointers to nodes with sources, used for quick access
+ std::map<am_domainID_t,std::vector<CAmRoutingNode*>> mNodeListSinks; //!< map with pointers to nodes with sinks, used for quick access
+ std::map<am_domainID_t,std::vector<CAmRoutingNode*>> mNodeListGateways; //!< map with pointers to nodes with gateways, used for quick access
std::map<am_domainID_t,std::vector<CAmRoutingNode*>> mNodeListConverters;//!< map with pointers to nodes with converters, used for quick access
- am_Error_e determineConnectionFormatsForPath(am_Route_s & routeObjects, std::vector<CAmRoutingNode*> & nodes, std::vector<am_Route_s> & result);
- am_Error_e doConnectionFormatsForPath(am_Route_s & routeObjects,
- std::vector<CAmRoutingNode*> & route,
- std::vector<am_RoutingElement_s>::iterator routingElementIterator,
- std::vector<CAmRoutingNode*>::iterator routeIterator,
- std::vector<am_Route_s> & result);
-
-
/**
* Check whether given converter or gateway has been connected.
*
@@ -176,86 +173,119 @@ class CAmRouter
{
return mpDatabaseHandler->isComponentConnected(comp);
}
- void generateAllPaths(const CAmRoutingNode & src,
- const CAmRoutingNode & dst,
- const bool includeCycles,
- std::function<void(const std::vector<CAmRoutingNode*> & path)> cb);
- void goThroughAllPaths(const CAmRoutingNode & dst,
- std::vector<CAmRoutingNode*> & visited,
- std::vector<am_domainID_t> & visitedDomains,
- std::function<void(const std::vector<CAmRoutingNode*> & path)> cb);
-
-#ifdef ROUTING_BUILD_CONNECTIONS
+
/**
- * Connects all converters to its sink and sources if possible.
+ * Connect all converters to its sink and sources if possible.
*
*/
void constructConverterConnections();
/**
- * Connects all gateways to its sink and sources if possible.
+ * Connect all gateways to its sink and sources if possible.
*
*/
void constructGatewayConnections();
/**
- * Connects all sources to the sinks if possible.
+ * Connect all sources to the sinks if possible.
*
*/
void constructSourceSinkConnections();
-#else
+
/**
- * Construct a list with all vertices
+ * Construct list with all vertices
*/
void getVerticesForNode(const CAmRoutingNode & node, CAmRoutingListVertices & list);
/**
- * Construct a list with all vertices from given source.
+ * Construct list with all vertices from given source.
*/
void getVerticesForSource(const CAmRoutingNode & node, CAmRoutingListVertices & list);
/**
- * Construct a list with all vertices from given sink.
+ * Construct list with all vertices from given sink.
*/
void getVerticesForSink(const CAmRoutingNode & node, CAmRoutingListVertices & list);
/**
- * Construct a list with all vertices from given converter.
+ * Construct list with all vertices from given converter.
*/
void getVerticesForConverter(const CAmRoutingNode & node, CAmRoutingListVertices & list);
/**
- * Construct a list with all vertices from given gateway.
+ * Construct list with all vertices from given gateway.
*/
void getVerticesForGateway(const CAmRoutingNode & node, CAmRoutingListVertices & list);
-#endif
+
+ /**
+ * Connection format permutations.
+ */
+ am_Error_e determineConnectionFormatsForPath(am_Route_s & routeObjects, std::vector<CAmRoutingNode*> & nodes, std::vector<am_Route_s> & result);
+ am_Error_e doConnectionFormatsForPath(am_Route_s & routeObjects,
+ std::vector<CAmRoutingNode*> & route,
+ std::vector<am_RoutingElement_s>::iterator routingElementIterator,
+ std::vector<CAmRoutingNode*>::iterator routeIterator,
+ std::vector<am_Route_s> & result);
+ am_Error_e cfPermutationsForPath(am_Route_s shortestRoute, std::vector<CAmRoutingNode*> resultNodesPath, std::vector<am_Route_s>& resultPath);
+
+ /**
+ * Helper method.
+ */
+ static int insertPostion(const std::vector<CAmRoutingNode*>& path, const std::vector<std::vector<CAmRoutingNode*> >& nodes) ;
+
public:
CAmRouter(IAmDatabaseHandler* iDatabaseHandler, CAmControlSender* iSender);
~CAmRouter();
+ unsigned getMaxAllowedCycles() { return mMaxAllowedCycles; }
+ void setMaxAllowedCycles(unsigned count) { mMaxAllowedCycles = count; }
+
+ unsigned getMaxPathCount() { return mMaxPathCount; }
+ void setMaxPathCount(unsigned count) { mMaxPathCount = count; }
+
/**
- * Finds all possible paths between given source and sink.
+ * Find first mMaxPathCount paths between given source and sink.
*
* @param onlyfree only disconnected elements should be included or not.
- * @param sourceID starting point.
- * @param sinkID ending point.
+ * @param sourceID start point.
+ * @param sinkID end point.
* @param returnList list with all possible paths
* @return E_OK on success(0 or more paths) or E_NOT_POSSIBLE on failure.
*/
am_Error_e getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s>& returnList);
- am_Error_e getRoute(const bool onlyfree, const am_Source_s & aSource, const am_Sink_s & aSink, std::vector<am_Route_s> & listRoutes);
+ am_Error_e getRoute(const bool onlyfree, const am_Source_s & source, const am_Sink_s & sink, std::vector<am_Route_s> & listRoutes);
- am_Error_e getAllPaths(CAmRoutingNode & aSource, CAmRoutingNode & aSink,
- std::vector<am_Route_s> & resultPath, std::vector<std::vector<CAmRoutingNode*>> & resultNodesPath,
-#if !defined(ROUTING_BUILD_CONNECTIONS)
- __attribute__((unused))
-#endif
- const bool includeCycles = false);
-#ifdef ROUTING_BUILD_CONNECTIONS
- void getShortestPath(const CAmRoutingNode & source, const CAmRoutingNode & destination, std::vector<CAmRoutingNode*> & resultPath);
- void getShortestPath(CAmRoutingNode & aSource, CAmRoutingNode & aSink, am_Route_s & resultPath, std::vector<CAmRoutingNode*> & resultNodesPath);
-#endif
+ /**
+ * Find first mMaxPathCount paths between given source and sink after the nodes have been loaded.
+ *
+ * @param sourceID start point.
+ * @param sinkID end point.
+ * @param returnList list with all possible paths
+ * @return E_OK on success(0 or more paths) or E_NOT_POSSIBLE on failure.
+ */
+ am_Error_e getRouteFromLoadedNodes(const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s> & returnList);
+ am_Error_e getRouteFromLoadedNodes(const am_Source_s & aSource, const am_Sink_s & aSink, std::vector<am_Route_s> & listRoutes);
+
+ /**
+ * Find first mMaxPathCount paths between given source and sink. This method should be called only after 'load' has been called.
+ *
+ * @param source start point.
+ * @param sink end point.
+ * @param returnList list with all possible paths.
+ * @return E_OK on success(0 or more paths) or E_NOT_POSSIBLE on failure.
+ */
+ am_Error_e getFirstNShortestPaths(CAmRoutingNode & source, CAmRoutingNode & sink, std::vector<am_Route_s> & resultPath);
+
+ /**
+ * Find the shortest path between given source and sink. This method should be called only after 'load' has been called.
+ *
+ * @param source start point.
+ * @param sink end point.
+ * @param returnList list with the connection format permutations of the shortest path.
+ * @return E_OK on success(0 or more paths) or E_NOT_POSSIBLE on failure.
+ */
+ am_Error_e getShortestPath(CAmRoutingNode & source, CAmRoutingNode & sink, std::vector<am_Route_s> & resultPath);
static bool getAllowedFormatsFromConvMatrix( const std::vector<bool> & convertionMatrix,
const std::vector<am_CustomConnectionFormat_t> & listSourceFormats,
@@ -274,8 +304,8 @@ public:
std::vector<CAmRoutingNode*>::iterator iteratorSink,
std::vector<am_CustomConnectionFormat_t> & outConnectionFormats);
- static bool shouldGoInDomain(const std::vector<am_domainID_t> & visitedDomains, const am_domainID_t nodeDomainID);
-
+ static bool shouldGoInDomain(const std::vector<am_domainID_t> & visitedDomains, const am_domainID_t nodeDomainID, const unsigned maxCyclesNumber);
+ bool shouldGoInDomain(const std::vector<am_domainID_t> & visitedDomains, const am_domainID_t nodeDomainID);
/**
* Returns a sink node with given sinkID.
*
@@ -313,6 +343,20 @@ public:
void load(const bool onlyFree);
void clear();
+
+ /**
+ * DEPRECATED!
+ */
+public:
+ am_Error_e getAllPaths(CAmRoutingNode & aSource,
+ CAmRoutingNode & aSink,
+ std::vector<am_Route_s> & resultPath,
+ std::vector<std::vector<CAmRoutingNode*>> & resultNodesPath,
+ const bool includeCycles = false)
+ __attribute__((deprecated("You should use am_Error_e getFirstNShortestPaths(CAmRoutingNode &, CAmRoutingNode &, std::vector<am_Route_s> &) instead!")));
+
+ void getShortestPath(CAmRoutingNode & aSource, CAmRoutingNode & aSink, am_Route_s & resultPath, std::vector<CAmRoutingNode*> & resultNodesPath)
+ __attribute__((deprecated("You should use am_Error_e getShortestPath(CAmRoutingNode &, CAmRoutingNode &, std::vector<am_Route_s> &) instead!")));
};
} /* namespace am */
#endif /* ROUTER_H_ */
diff --git a/AudioManagerCore/src/CAmRouter.cpp b/AudioManagerCore/src/CAmRouter.cpp
index f59af24..7ee71ba 100644
--- a/AudioManagerCore/src/CAmRouter.cpp
+++ b/AudioManagerCore/src/CAmRouter.cpp
@@ -57,6 +57,8 @@ CAmRouter::CAmRouter(IAmDatabaseHandler* iDatabaseHandler, CAmControlSender* iSe
mpDatabaseHandler(iDatabaseHandler), //
mpControlSender(iSender),
mOnlyFreeConversionNodes(false),
+ mMaxAllowedCycles(MAX_ALLOWED_DOMAIN_CYCLES),
+ mMaxPathCount(MAX_ROUTING_PATHS),
mRoutingGraph(),
mNodeListSources(),
mNodeListSinks(),
@@ -81,52 +83,51 @@ CAmRouter::~CAmRouter()
*/
am_Error_e CAmRouter::getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s> & returnList)
{
- returnList.clear();
- am_Source_s source;
- am_Sink_s sink;
- am_Error_e error = mpDatabaseHandler->getSourceInfoDB(sourceID, source);
- if(error!=E_OK)
- return error;
- error = mpDatabaseHandler->getSinkInfoDB(sinkID, sink);
- if(error!=E_OK)
- return error;
- error = getRoute(onlyfree, source, sink, returnList);
- return error;
+ load(onlyfree);
+ return getRouteFromLoadedNodes(sourceID, sinkID, returnList);
}
am_Error_e CAmRouter::getRoute(const bool onlyfree, const am_Source_s & aSource, const am_Sink_s & aSink, std::vector<am_Route_s> & listRoutes)
{
- am_Error_e error;
- load(onlyfree);
+ return getRoute(onlyfree, aSource.sourceID, aSink.sinkID, listRoutes);
+}
- CAmRoutingNode* pRootSource = sourceNodeWithID(aSource.sourceID);
- CAmRoutingNode* pRootSink = sinkNodeWithID(aSink.sinkID);
+am_Error_e CAmRouter::getRouteFromLoadedNodes(const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s> & returnList)
+{
+ returnList.clear();
- assert(pRootSource);
- assert(pRootSink);
+ CAmRoutingNode* pRootSource = sourceNodeWithID(sourceID);
+ CAmRoutingNode* pRootSink = sinkNodeWithID(sinkID);
-#ifdef TRACE_GRAPH
- mRoutingGraph.trace([&](const CAmRoutingNode & node, const std::vector<CAmVertex<am_RoutingNodeData_s,uint16_t>*> & list) {
- std::cout << "Node " << node.getIndex() << ":";
- ((CAmRoutingNode &)node).getData().trace();
- std::cout << "-->[";
- int count = 0;
- std::for_each(list.begin(), list.end(), [&](const CAmVertex<am_RoutingNodeData_s,uint16_t>* refVertex){
- am::CAmNode<am::am_RoutingNodeData_s>* data = refVertex->getNode();
- if(count>0)
- std::cout << ", ";
- std::cout << "Node " << data->getIndex() << ":";
- data->getData().trace();
- count++;
- });
- std::cout << "]" << std::endl;
- });
-#endif
+ if(!pRootSource || !pRootSink)
+ return E_NON_EXISTENT;
- std::vector<std::vector<CAmRoutingNode*>> pathNodes;
- error = getAllPaths(*pRootSource, *pRootSink, listRoutes, pathNodes);
- return error;
+ //try to find paths without cycles
+ const unsigned cycles = mMaxAllowedCycles;
+ mMaxAllowedCycles = 0;
+
+ am_Error_e error = getFirstNShortestPaths(*pRootSource, *pRootSink, returnList);
+
+ mMaxAllowedCycles = cycles;
+
+ //if no paths have been found, we start a second search with cycles.
+ if( !returnList.size() && cycles>0 )
+ {
+ error = getFirstNShortestPaths(*pRootSource, *pRootSink, returnList);
+ }
+
+ /* For shortest path use the following call:
+ *
+ * error = getShortestPath(*pRootSource, *pRootSink, listRoutes);
+ */
+ return error;
+}
+
+
+am_Error_e CAmRouter::getRouteFromLoadedNodes(const am_Source_s & aSource, const am_Sink_s & aSink, std::vector<am_Route_s> & listRoutes)
+{
+ return getRouteFromLoadedNodes(aSource.sourceID, aSink.sinkID, listRoutes);
}
void CAmRouter::load(const bool onlyFree)
@@ -138,32 +139,53 @@ void CAmRouter::load(const bool onlyFree)
nodeDataSrc.type = CAmNodeDataType::SOURCE;
mpDatabaseHandler->enumerateSources([&](const am_Source_s & obj){
nodeDataSrc.data.source = (am_Source_s*)&obj;
- mNodeListSources[nodeDataSrc.data.source->domainID].push_back(&mRoutingGraph.addNode(nodeDataSrc));
- });
+ auto node = &mRoutingGraph.addNode(nodeDataSrc);
+ mNodeListSources[nodeDataSrc.data.source->domainID].push_back(node);
+ });
am_RoutingNodeData_s nodeDataSink;
nodeDataSink.type = CAmNodeDataType::SINK;
mpDatabaseHandler->enumerateSinks([&](const am_Sink_s & obj){
nodeDataSink.data.sink = (am_Sink_s*)&obj;
- mNodeListSinks[nodeDataSink.data.sink->domainID].push_back(&mRoutingGraph.addNode(nodeDataSink));
- });
+ auto node = &mRoutingGraph.addNode(nodeDataSink);
+ mNodeListSinks[nodeDataSink.data.sink->domainID].push_back(node);
+ });
am_RoutingNodeData_s nodeDataGateway;
nodeDataGateway.type = CAmNodeDataType::GATEWAY;
mpDatabaseHandler->enumerateGateways([&](const am_Gateway_s & obj){
nodeDataGateway.data.gateway = (am_Gateway_s*)&obj;
- mNodeListGateways[nodeDataGateway.data.gateway->controlDomainID].push_back(&mRoutingGraph.addNode(nodeDataGateway));
+ auto node = &mRoutingGraph.addNode(nodeDataGateway);
+ mNodeListGateways[nodeDataGateway.data.gateway->controlDomainID].push_back(node);
});
am_RoutingNodeData_s nodeDataConverter;
nodeDataConverter.type = CAmNodeDataType::CONVERTER;
mpDatabaseHandler->enumerateConverters([&](const am_Converter_s & obj){
nodeDataConverter.data.converter = (am_Converter_s*)&obj;
- mNodeListConverters[nodeDataConverter.data.converter->domainID].push_back(&mRoutingGraph.addNode(nodeDataConverter));
+ auto node = &mRoutingGraph.addNode(nodeDataConverter);
+ mNodeListConverters[nodeDataConverter.data.converter->domainID].push_back(node);
});
-#ifdef ROUTING_BUILD_CONNECTIONS
constructConverterConnections();
constructGatewayConnections();
constructSourceSinkConnections();
+
+#ifdef TRACE_GRAPH
+ mRoutingGraph.trace([&](const CAmRoutingNode & node, const std::vector<CAmVertex<am_RoutingNodeData_s,uint16_t>*> & list) {
+ std::cout << "Node " << node.getIndex() << ":";
+ ((CAmRoutingNode &)node).getData().trace();
+ std::cout << "-->[";
+ int count = 0;
+ std::for_each(list.begin(), list.end(), [&](const CAmVertex<am_RoutingNodeData_s,uint16_t>* refVertex){
+ am::CAmNode<am::am_RoutingNodeData_s>* data = refVertex->getNode();
+ if(count>0)
+ std::cout << ", ";
+ std::cout << "Node " << data->getIndex() << ":";
+ data->getData().trace();
+ count++;
+ });
+ std::cout << "]" << std::endl;
+ });
#endif
+
}
void CAmRouter::clear()
@@ -249,8 +271,6 @@ CAmRoutingNode* CAmRouter::gatewayNodeWithSinkID(const am_sinkID_t sinkID)
return NULL;
}
-#ifdef ROUTING_BUILD_CONNECTIONS
-
void CAmRouter::constructSourceSinkConnections()
{
std::vector<am_CustomConnectionFormat_t> intersection;
@@ -353,7 +373,6 @@ void CAmRouter::constructConverterConnections()
}
}
}
-#else
void CAmRouter::getVerticesForSource(const CAmRoutingNode & node, CAmRoutingListVertices & list)
{
@@ -470,8 +489,6 @@ void CAmRouter::getVerticesForNode(
}
}
-#endif
-
am_Error_e CAmRouter::determineConnectionFormatsForPath(am_Route_s & routeObjects, std::vector<CAmRoutingNode*> & nodes, std::vector<am_Route_s> & result)
{
std::vector<am_RoutingElement_s>::iterator routingElementIterator = routeObjects.route.begin();
@@ -570,31 +587,66 @@ am_Error_e CAmRouter::doConnectionFormatsForPath(am_Route_s & routeObjects,
}
}
-#ifdef ROUTING_BUILD_CONNECTIONS
-
-void CAmRouter::getShortestPath(const CAmRoutingNode & source,
- const CAmRoutingNode & destination,
- std::vector<CAmRoutingNode*> & resultPath)
+am_Error_e CAmRouter::cfPermutationsForPath(am_Route_s shortestRoute, std::vector<CAmRoutingNode*> resultNodesPath, std::vector<am_Route_s>& resultPath)
{
- mRoutingGraph.getShortestPath(source, destination, resultPath);
+ std::vector<am_Route_s> result;
+ am_Error_e err = determineConnectionFormatsForPath(shortestRoute, resultNodesPath, result);
+ if (err != E_UNKNOWN)
+ {
+ resultPath.insert(resultPath.end(), result.begin(), result.end());
+#ifdef TRACE_GRAPH
+ std::cout
+ << "Successfully determined connection formats for path from source:"
+ << shortestRoute.sourceID << " to sink:" << shortestRoute.sinkID
+ << "\n";
+ for (auto routeConnectionFormats : result)
+ {
+ std::cout << "[";
+ for (auto it = routeConnectionFormats.route.begin();it != routeConnectionFormats.route.end(); it++)
+ {
+ am_RoutingElement_s& routingElement = *it;
+ if (it - routeConnectionFormats.route.begin() > 0)
+ std::cout << " -> ";
+
+ std::cout << routingElement.sourceID << ":"
+ << routingElement.sinkID << " CF:"
+ << routingElement.connectionFormat << " D:"
+ << routingElement.domainID;
+ }
+ std::cout << "]\n";
+ }
+#endif
+ }
+#ifdef TRACE_GRAPH
+ else
+ {
+ std::cout
+ << "Error by determining connection formats for path from source:"
+ << shortestRoute.sourceID << " to sink:" << shortestRoute.sinkID
+ << "\n";
+ }
+#endif
+ return err;
}
-void CAmRouter::getShortestPath(CAmRoutingNode & aSource, CAmRoutingNode & aSink,
- am_Route_s & resultPath, std::vector<CAmRoutingNode*> & resultNodesPath)
+am_Error_e CAmRouter::getShortestPath(CAmRoutingNode & aSource, CAmRoutingNode & aSink, std::vector<am_Route_s> & resultPath)
{
- am_RoutingElement_s * element;
+ am_Error_e err = E_OK;
+ am_Route_s shortestRoute;
+ std::vector<CAmRoutingNode*> resultNodesPath;
am_RoutingNodeData_s & sinkNodeData = aSink.getData();
am_RoutingNodeData_s & sourceNodeData = aSource.getData();
- resultPath.sinkID = sinkNodeData.data.sink->sinkID;
- resultPath.sourceID = sourceNodeData.data.source->sourceID;
+ shortestRoute.sinkID = sinkNodeData.data.sink->sinkID;
+ shortestRoute.sourceID = sourceNodeData.data.source->sourceID;
- std::function<void(const am_GraphPathPosition_e, CAmRoutingNode &)> cb = [&](const am_GraphPathPosition_e, CAmRoutingNode & object)
- {
+ mRoutingGraph.getShortestPath(aSource, aSink, [&shortestRoute, &resultNodesPath](const am_GraphPathPosition_e position, CAmRoutingNode & object){
+ am_RoutingElement_s * element;
+ //reverse order
resultNodesPath.insert(resultNodesPath.begin(), (CAmRoutingNode*)&object);
am_RoutingNodeData_s & routingData = object.getData();
if(routingData.type==CAmNodeDataType::SINK)
{
- auto iter = resultPath.route.emplace(resultPath.route.begin());
+ auto iter = shortestRoute.route.emplace(shortestRoute.route.begin());
element = &(*iter);
element->domainID = routingData.data.sink->domainID;
element->sinkID = routingData.data.sink->sinkID;
@@ -606,87 +658,195 @@ void CAmRouter::getShortestPath(CAmRoutingNode & aSource, CAmRoutingNode & aSink
element->sourceID = routingData.data.source->sourceID;
element->connectionFormat = CF_UNKNOWN;
}
- };
- mRoutingGraph.getShortestPath(aSource, aSink, cb);
-}
+ });
-#endif
+ if(shortestRoute.route.size())
+ {
+ err = cfPermutationsForPath(shortestRoute, resultNodesPath, resultPath);
+ }
+ return err;
+}
-am_Error_e CAmRouter::getAllPaths(CAmRoutingNode & aSource,
- CAmRoutingNode & aSink,
- std::vector<am_Route_s> & resultPath,
- std::vector<std::vector<CAmRoutingNode*>> & resultNodesPath,
- const bool includeCycles)
-{
-#ifndef ROUTING_BUILD_CONNECTIONS
- bool cycles = false;
-#else
- bool cycles = includeCycles;
-#endif
- if(((CAmRoutingNode*)&aSource)->getData().type!=CAmNodeDataType::SOURCE ||
- ((CAmRoutingNode*)&aSink)->getData().type!=CAmNodeDataType::SINK)
- return E_NOT_POSSIBLE;
+void CAmRouter::getShortestPath(CAmRoutingNode & aSource, CAmRoutingNode & aSink, am_Route_s & path, std::vector<CAmRoutingNode*> & resultNodesPath)
+{
+ am_Route_s shortestRoute;
+ am_RoutingNodeData_s & sinkNodeData = aSink.getData();
+ am_RoutingNodeData_s & sourceNodeData = aSource.getData();
+ shortestRoute.sinkID = sinkNodeData.data.sink->sinkID;
+ shortestRoute.sourceID = sourceNodeData.data.source->sourceID;
- uint8_t errorsCount = 0, successCount = 0;
- generateAllPaths(aSource, aSink, cycles, [&](const std::vector<CAmRoutingNode*> & path) {
- resultNodesPath.push_back(path);
- am_Route_s nextRoute;
- nextRoute.sinkID = aSink.getData().data.sink->sinkID;
- nextRoute.sourceID = aSource.getData().data.source->sourceID;
+ mRoutingGraph.getShortestPath(aSource, aSink, [&shortestRoute, &resultNodesPath](const am_GraphPathPosition_e position, CAmRoutingNode & object){
am_RoutingElement_s * element;
- for(auto it = path.begin(); it!=path.end(); it++)
+ //reverse order
+ resultNodesPath.insert(resultNodesPath.begin(), (CAmRoutingNode*)&object);
+ am_RoutingNodeData_s & routingData = object.getData();
+ if(routingData.type==CAmNodeDataType::SINK)
{
- am_RoutingNodeData_s & routingData = (*it)->getData();
- if(routingData.type==CAmNodeDataType::SOURCE)
- {
- auto iter = nextRoute.route.emplace(nextRoute.route.end());
- element = &(*iter);
- element->domainID = routingData.data.source->domainID;
- element->sourceID = routingData.data.source->sourceID;
- element->connectionFormat = CF_UNKNOWN;
- }
- else if(routingData.type==CAmNodeDataType::SINK)
- {
- element->domainID = routingData.data.sink->domainID;
- element->sinkID = routingData.data.sink->sinkID;
- element->connectionFormat = CF_UNKNOWN;
- }
+ auto iter = shortestRoute.route.emplace(shortestRoute.route.begin());
+ element = &(*iter);
+ element->domainID = routingData.data.sink->domainID;
+ element->sinkID = routingData.data.sink->sinkID;
+ element->connectionFormat = CF_UNKNOWN;
}
- std::vector<am_Route_s> result;
- am_Error_e err = determineConnectionFormatsForPath(nextRoute, (std::vector<CAmRoutingNode*> &)path, result);
- if(err==E_UNKNOWN)
+ else if(routingData.type==CAmNodeDataType::SOURCE)
{
- errorsCount++;
-#ifdef TRACE_GRAPH
- std::cout<<"Error by determining connection formats for path from source:"<<nextRoute.sourceID<<" to sink:"<<nextRoute.sinkID<<"\n";
-#endif
+ element->domainID = routingData.data.source->domainID;
+ element->sourceID = routingData.data.source->sourceID;
+ element->connectionFormat = CF_UNKNOWN;
+ }
+ });
+
+ if(shortestRoute.route.size())
+ {
+ std::vector<am_Route_s> resultPath;
+ cfPermutationsForPath(shortestRoute, resultNodesPath, resultPath);
+ if(resultPath.size())
+ path = resultPath.front();
+ }
+}
+
+int CAmRouter::insertPostion(const std::vector<CAmRoutingNode*>& path, const std::vector<std::vector<CAmRoutingNode*> >& nodes)
+{
+ int index = 0;
+ if (!nodes.empty()) {
+ auto itNodes = nodes.begin();
+ for (; itNodes != nodes.end(); itNodes++) {
+ if (itNodes->size() > path.size())
+ break;
}
+ if (itNodes == nodes.end())
+ index = nodes.size();
+ else
+ index = itNodes - nodes.begin();
+ }
+ return index;
+}
+
+am_Error_e CAmRouter::getAllPaths(CAmRoutingNode & aSource,
+ CAmRoutingNode & aSink,
+ std::vector<am_Route_s> & resultPath,
+ std::vector<std::vector<CAmRoutingNode*>> & resultNodesPath,
+ const bool includeCycles)
+{
+
+ if( aSource.getData().type!=CAmNodeDataType::SOURCE || aSink.getData().type!=CAmNodeDataType::SINK )
+ return E_NOT_POSSIBLE;
+
+ unsigned cycles;
+ if(includeCycles)
+ cycles = UINT_MAX;
+ else
+ cycles = 0;
+
+ uint8_t errorsCount = 0, successCount = 0;
+ const am_sinkID_t sinkID = aSink.getData().data.sink->sinkID;
+ const am_sourceID_t sourceID = aSource.getData().data.source->sourceID;
+ std::vector<am_Route_s> paths;
+ std::vector<am_domainID_t> visitedDomains;
+ visitedDomains.push_back(((CAmRoutingNode*)&aSource)->getData().domainID());
+ mRoutingGraph.getAllPaths(aSource,
+ aSink,
+ [&visitedDomains, &cycles](const CAmRoutingNode * node)->bool{ return CAmRouter::shouldGoInDomain(visitedDomains, node->getData().domainID(), cycles); },
+ [&visitedDomains](const CAmRoutingNode * node){ visitedDomains.push_back(node->getData().domainID()); },
+ [&visitedDomains](const CAmRoutingNode * node){ visitedDomains.erase(visitedDomains.end()-1); },
+ [&resultPath, &resultNodesPath, &paths, &errorsCount, &successCount, &sinkID, &sourceID](const std::vector<CAmRoutingNode*> & path) {
+ int index = CAmRouter::insertPostion(path, resultNodesPath);
+ resultNodesPath.emplace(resultNodesPath.begin()+index);
+ paths.emplace(paths.begin()+index);
+ resultNodesPath[index] = path;
+ am_Route_s & nextRoute = paths[index];
+ nextRoute.sinkID = sinkID;
+ nextRoute.sourceID = sourceID;
+ am_RoutingElement_s * element;
+ for(auto it = path.begin(); it!=path.end(); it++)
+ {
+ am_RoutingNodeData_s & routingData = (*it)->getData();
+ if(routingData.type==CAmNodeDataType::SOURCE)
+ {
+ auto iter = nextRoute.route.emplace(nextRoute.route.end());
+ element = &(*iter);
+ element->domainID = routingData.data.source->domainID;
+ element->sourceID = routingData.data.source->sourceID;
+ element->connectionFormat = CF_UNKNOWN;
+ }
+ else if(routingData.type==CAmNodeDataType::SINK)
+ {
+ element->domainID = routingData.data.sink->domainID;
+ element->sinkID = routingData.data.sink->sinkID;
+ element->connectionFormat = CF_UNKNOWN;
+ }
+ }
+ });
+
+ for(auto it = paths.begin(); successCount<mMaxPathCount && it!=paths.end(); it++)
+ {
+ if(cfPermutationsForPath(*it, resultNodesPath[it-paths.begin()], resultPath)==E_UNKNOWN)
+ errorsCount++;
else
- {
- resultPath.insert(resultPath.end(), result.begin(), result.end());
-#ifdef TRACE_GRAPH
- std::cout<<"Successfully determined connection formats for path from source:"<<nextRoute.sourceID<<" to sink:"<<nextRoute.sinkID<<"\n";
- for(auto routeConnectionFormats: result)
- {
- for(auto it = routeConnectionFormats.route.begin(); it!=routeConnectionFormats.route.end(); it++)
- {
- am_RoutingElement_s & routingElement = *it;
- std::cout<<"["
- <<routingElement.sourceID
- <<"->"
- <<routingElement.sinkID
- <<" CF:"
- <<routingElement.connectionFormat
- <<" D:"
- <<routingElement.domainID
- <<"]";
- }
- std::cout<<"\n";
- }
-#endif
successCount++;
- }
+ }
+
+ if(successCount)
+ return E_OK;
+ if(errorsCount)
+ return E_NOT_POSSIBLE;
+ return E_OK;
+}
+
+am_Error_e CAmRouter::getFirstNShortestPaths(CAmRoutingNode & aSource, CAmRoutingNode & aSink, std::vector<am_Route_s> & resultPath)
+{
+ if( aSource.getData().type!=CAmNodeDataType::SOURCE || aSink.getData().type!=CAmNodeDataType::SINK )
+ return E_NOT_POSSIBLE;
+ const unsigned cycles = mMaxAllowedCycles;
+ uint8_t errorsCount = 0, successCount = 0;
+ const am_sinkID_t sinkID = aSink.getData().data.sink->sinkID;
+ const am_sourceID_t sourceID = aSource.getData().data.source->sourceID;
+ std::vector<am_Route_s> paths;
+ std::vector<std::vector<CAmRoutingNode*>> nodes;
+ std::vector<am_domainID_t> visitedDomains;
+ visitedDomains.push_back(((CAmRoutingNode*)&aSource)->getData().domainID());
+ mRoutingGraph.getAllPaths(aSource,
+ aSink,
+ [&visitedDomains, &cycles](const CAmRoutingNode * node)->bool{ return CAmRouter::shouldGoInDomain(visitedDomains, node->getData().domainID(), cycles); },
+ [&visitedDomains](const CAmRoutingNode * node){ visitedDomains.push_back(node->getData().domainID()); },
+ [&visitedDomains](const CAmRoutingNode * node){ visitedDomains.erase(visitedDomains.end()-1); },
+ [&resultPath, &nodes, &paths, &errorsCount, &successCount, &sinkID, &sourceID](const std::vector<CAmRoutingNode*> & path) {
+ int index = CAmRouter::insertPostion(path, nodes);
+ nodes.emplace(nodes.begin()+index);
+ paths.emplace(paths.begin()+index);
+ nodes[index] = path;
+ am_Route_s & nextRoute = paths[index];
+ nextRoute.sinkID = sinkID;
+ nextRoute.sourceID = sourceID;
+ am_RoutingElement_s * element;
+ for(auto it = path.begin(); it!=path.end(); it++)
+ {
+ am_RoutingNodeData_s & routingData = (*it)->getData();
+ if(routingData.type==CAmNodeDataType::SOURCE)
+ {
+ auto iter = nextRoute.route.emplace(nextRoute.route.end());
+ element = &(*iter);
+ element->domainID = routingData.data.source->domainID;
+ element->sourceID = routingData.data.source->sourceID;
+ element->connectionFormat = CF_UNKNOWN;
+ }
+ else if(routingData.type==CAmNodeDataType::SINK)
+ {
+ element->domainID = routingData.data.sink->domainID;
+ element->sinkID = routingData.data.sink->sinkID;
+ element->connectionFormat = CF_UNKNOWN;
+ }
+ }
});
+
+ for(auto it = paths.begin(); successCount<mMaxPathCount && it!=paths.end(); it++)
+ {
+ if(cfPermutationsForPath(*it, nodes[it-paths.begin()], resultPath)==E_UNKNOWN)
+ errorsCount++;
+ else
+ successCount++;
+ }
+
if(successCount)
return E_OK;
if(errorsCount)
@@ -694,92 +854,35 @@ am_Error_e CAmRouter::getAllPaths(CAmRoutingNode & aSource,
return E_OK;
}
-bool CAmRouter::shouldGoInDomain(const std::vector<am_domainID_t> & visitedDomains, const am_domainID_t nodeDomainID)
+bool CAmRouter::shouldGoInDomain(const std::vector<am_domainID_t> & visitedDomains, const am_domainID_t nodeDomainID, const unsigned maxCyclesNumber)
{
+ unsigned recourseCounter(0);
if(visitedDomains.size())
{
if(visitedDomains.back()==nodeDomainID)
return true;
-
- for(auto it=visitedDomains.begin();it!=visitedDomains.end()-1; it++)
+ unsigned count = 0;
+ am_domainID_t lastDomain = 0;
+ for(auto it=visitedDomains.begin(); it!=visitedDomains.end()-1; it++)
{
- if(nodeDomainID==*it)
- return false;
+ if(lastDomain!=*it)
+ {
+ if(nodeDomainID==*it)
+ {
+ recourseCounter++;
+ if (recourseCounter>maxCyclesNumber)
+ return false;
+ }
+ lastDomain=*it;
+ }
}
}
return true;
}
-void CAmRouter::generateAllPaths(const CAmRoutingNode & src,
- const CAmRoutingNode & dst,
- const bool includeCycles,
- std::function<void(const std::vector<CAmRoutingNode*> & path)> cb)
-{
- if(!includeCycles)
- {
- std::vector<CAmRoutingNode*> visited;
- std::vector<am_domainID_t> visitedDomains;
- visited.push_back((CAmRoutingNode*)&src);
- visitedDomains.push_back(((CAmRoutingNode*)&src)->getData().domainID());
- ((CAmRoutingNode*)&src)->setStatus(GES_VISITED);
- goThroughAllPaths(dst, visited, visitedDomains, cb);
- }
- else
- mRoutingGraph.getAllPaths(src, dst, cb);
-}
-
-void CAmRouter::goThroughAllPaths(const CAmRoutingNode & dst,
- std::vector<CAmRoutingNode*> & visited,
- std::vector<am_domainID_t> & visitedDomains,
- std::function<void(const std::vector<CAmRoutingNode*> & path)> cb)
+bool CAmRouter::shouldGoInDomain(const std::vector<am_domainID_t> & visitedDomains, const am_domainID_t nodeDomainID)
{
-#ifndef ROUTING_BUILD_CONNECTIONS
- CAmRoutingListVertices vertices;
- getVerticesForNode(*visited.back(), vertices);
- const CAmRoutingListVertices * nodes = &vertices;
-#else
- const CAmRoutingListVertices * nodes = mRoutingGraph.getVertexList()[visited.back()->getIndex()];
-#endif
- CAmRoutingListVertices::const_iterator vItr(nodes->begin());
- for (; vItr != nodes->end(); ++vItr)
- {
- const CAmRoutingVertex & vertex = (*vItr);
- if(vertex.getNode()->getStatus()!=GES_NOT_VISITED || !shouldGoInDomain(visitedDomains, vertex.getNode()->getData().domainID()))
- continue;
- if (vertex.getNode()==&dst)
- {
- vertex.getNode()->setStatus(GES_IN_PROGRESS);
- visited.push_back(vertex.getNode());
- visitedDomains.push_back(vertex.getNode()->getData().domainID());
- //notify observer
- cb(visited);
- //remove last node from the list
- auto last = visited.end()-1;
- visited.erase(last);
- visitedDomains.erase(visitedDomains.end()-1);
- vertex.getNode()->setStatus(GES_NOT_VISITED);
- break;
- }
- }
- vItr = nodes->begin();
- //bfs like loop
- for (; vItr != nodes->end(); ++vItr)
- {
- const CAmRoutingVertex & vertex = (*vItr);
- if(vertex.getNode()->getStatus()!=GES_NOT_VISITED
- ||vertex.getNode()==&dst ||
- !shouldGoInDomain(visitedDomains, vertex.getNode()->getData().domainID()))
- continue;
- vertex.getNode()->setStatus(GES_IN_PROGRESS);
- visited.push_back(vertex.getNode());
- visitedDomains.push_back(vertex.getNode()->getData().domainID());
- goThroughAllPaths(dst, visited, visitedDomains, cb);
- //remove last node from the list
- auto last = visited.end()-1;
- visited.erase(last);
- visitedDomains.erase(visitedDomains.end()-1);
- vertex.getNode()->setStatus(GES_NOT_VISITED);
- }
+ return CAmRouter::shouldGoInDomain(visitedDomains, nodeDomainID, mMaxAllowedCycles);
}
bool CAmRouter::getAllowedFormatsFromConvMatrix( const std::vector<bool> & convertionMatrix,
@@ -872,4 +975,5 @@ am_Error_e CAmRouter::getSourceSinkPossibleConnectionFormats(std::vector<CAmRout
return (E_OK);
}
+
}
diff --git a/AudioManagerCore/test/AmRouterMapTest/CAmRouterMapTest.cpp b/AudioManagerCore/test/AmRouterMapTest/CAmRouterMapTest.cpp
index 9dd23af..ad886f4 100644
--- a/AudioManagerCore/test/AmRouterMapTest/CAmRouterMapTest.cpp
+++ b/AudioManagerCore/test/AmRouterMapTest/CAmRouterMapTest.cpp
@@ -167,12 +167,16 @@ void CAmRouterMapTest::enterConverterDB(const std::string & gwName,
ASSERT_EQ(E_OK, pDatabaseHandler.enterConverterDB(converter,converterID));
}
-void CAmRouterMapTest::getRoute(const bool onlyfree, const am_Source_s & aSource, const am_Sink_s & aSink, std::vector<am_Route_s> & listRoutes)
+void CAmRouterMapTest::getRoute(const bool onlyfree, const bool shouldReload, const am_Source_s & aSource, const am_Sink_s & aSink, std::vector<am_Route_s> & listRoutes, const unsigned countCycles, const unsigned pathsCount)
{
+ pRouter.setMaxAllowedCycles(countCycles);
+ pRouter.setMaxPathCount(pathsCount);
std::ios_base::fmtflags oldflags = std::cout.flags();
std::streamsize oldprecision = std::cout.precision();
auto t_start = std::chrono::high_resolution_clock::now();
- ASSERT_EQ(E_OK, pRouter.getRoute(onlyfree, aSource, aSink, listRoutes));
+ if(shouldReload)
+ pRouter.load(onlyfree);
+ ASSERT_EQ(E_OK, pRouter.getRouteFromLoadedNodes(aSource, aSink, listRoutes));
auto t_end = std::chrono::high_resolution_clock::now();
std::cout << std::fixed << std::setprecision(2);
std::cout << listRoutes.size() <<" routes from " << aSource.sourceID << " to " << aSink.sinkID;
@@ -181,12 +185,16 @@ void CAmRouterMapTest::getRoute(const bool onlyfree, const am_Source_s & aSource
std::cout.precision (oldprecision);
}
-void CAmRouterMapTest::getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s>& returnList)
+void CAmRouterMapTest::getRoute(const bool onlyfree, const bool shouldReload, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s>& returnList, const unsigned countCycles, const unsigned pathsCount)
{
+ pRouter.setMaxAllowedCycles(countCycles);
+ pRouter.setMaxPathCount(pathsCount);
std::ios_base::fmtflags oldflags = std::cout.flags();
std::streamsize oldprecision = std::cout.precision();
auto t_start = std::chrono::high_resolution_clock::now();
- ASSERT_EQ(E_OK, pRouter.getRoute(onlyfree, sourceID, sinkID, returnList));
+ if(shouldReload)
+ pRouter.load(onlyfree);
+ ASSERT_EQ(E_OK, pRouter.getRouteFromLoadedNodes(sourceID, sinkID, returnList));
auto t_end = std::chrono::high_resolution_clock::now();
std::cout << std::fixed << std::setprecision(2);
std::cout << returnList.size() <<" routes from " << sourceID << " to " << sinkID;
@@ -195,16 +203,14 @@ void CAmRouterMapTest::getRoute(const bool onlyfree, const am_sourceID_t sourceI
std::cout.precision (oldprecision);
}
-void CAmRouterMapTest::getAllPaths(CAmRoutingNode & aSource,
- CAmRoutingNode & aSink,
- std::vector<am_Route_s> & resultPath,
- std::vector<std::vector<CAmRoutingNode*>> & resultNodesPath,
- const bool includeCycles)
+void CAmRouterMapTest::getAllPaths(CAmRoutingNode & aSource, CAmRoutingNode & aSink, std::vector<am_Route_s> & resultPath, const unsigned countCycles, const unsigned pathsCount)
{
+ pRouter.setMaxAllowedCycles(countCycles);
+ pRouter.setMaxPathCount(pathsCount);
std::ios_base::fmtflags oldflags = std::cout.flags();
std::streamsize oldprecision = std::cout.precision();
auto t_start = std::chrono::high_resolution_clock::now();
- ASSERT_EQ(E_OK, pRouter.getAllPaths(aSource, aSink, resultPath, resultNodesPath, includeCycles));
+ ASSERT_EQ(E_OK, pRouter.getFirstNShortestPaths(aSource, aSink, resultPath));
auto t_end = std::chrono::high_resolution_clock::now();
std::cout << std::fixed << std::setprecision(2);
std::cout << resultPath.size()
@@ -218,19 +224,19 @@ void CAmRouterMapTest::getAllPaths(CAmRoutingNode & aSource,
TEST_F(CAmRouterMapTest,checkInsertedDomain)
{
std::vector<am_domainID_t> domains;
- ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 22));
+ ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 22, 0));
domains.push_back(22);
- ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 22));
+ ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 22, 0));
domains.push_back(22);
- ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 22));
- ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 50));
+ ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 22, 0));
+ ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 50, 0));
domains.push_back(30);
- ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 30));
- ASSERT_FALSE(CAmRouter::shouldGoInDomain(domains, 22));
+ ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 30, 0));
+ ASSERT_FALSE(CAmRouter::shouldGoInDomain(domains, 22, 0));
domains.push_back(30);
- ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 30));
- ASSERT_FALSE(CAmRouter::shouldGoInDomain(domains, 22));
- ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 60));
+ ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 30, 0));
+ ASSERT_FALSE(CAmRouter::shouldGoInDomain(domains, 22, 0));
+ ASSERT_TRUE(CAmRouter::shouldGoInDomain(domains, 60, 0));
}
//test that checks just sinks and source in a domain but connectionformats do not match
@@ -304,7 +310,7 @@ TEST_F(CAmRouterMapTest,simpleRoute2withDomainNoMatchFormats)
pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb);
pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb);
listRoutes.clear();
- getRoute(true, sourceDb, sinkDb, listRoutes);
+ getRoute(true, true, sourceDb, sinkDb, listRoutes);
ASSERT_EQ(static_cast<uint>(0), listRoutes.size());
}
@@ -379,7 +385,7 @@ TEST_F(CAmRouterMapTest,simpleRoute2withDomain)
pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb);
pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb);
listRoutes.clear();
- getRoute(true, sourceDb, sinkDb, listRoutes);
+ getRoute(true, true, sourceDb, sinkDb, listRoutes);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0]));
}
@@ -498,7 +504,7 @@ TEST_F(CAmRouterMapTest,simpleRoute2DomainsOnlyFree)
pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb);
pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb);
- getRoute(true,sourceID,sinkID,listRoutes);
+ getRoute(true, true,sourceID,sinkID,listRoutes);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0]));
}
@@ -633,11 +639,11 @@ TEST_F(CAmRouterMapTest,simpleRoute2DomainsOnlyFreeNotFree)
pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb);
pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb);
listRoutes.clear();
- getRoute(true, sourceDb, sinkDb, listRoutes);
+ getRoute(true, true, sourceDb, sinkDb, listRoutes);
ASSERT_EQ(static_cast<uint>(0), listRoutes.size());
listRoutes.clear();
- getRoute(false, sourceDb, sinkDb, listRoutes);
+ getRoute(false, true, sourceDb, sinkDb, listRoutes);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0]));
}
@@ -784,7 +790,7 @@ TEST_F(CAmRouterMapTest,simpleRoute2DomainsCircularGWOnlyFree)
pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb);
pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb);
listRoutes.clear();
- getRoute(true, sourceDb, sinkDb, listRoutes);
+ getRoute(true, true, sourceDb, sinkDb, listRoutes);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0]));
}
@@ -957,7 +963,7 @@ TEST_F(CAmRouterMapTest,simpleRoute3DomainsListConnectionFormats_2)
am::am_Sink_s sinkDb;
pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb);
pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb);
- getRoute(false, sourceDb, sinkDb, listRoutes);
+ getRoute(false, true, sourceDb, sinkDb, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0]));
}
@@ -1124,12 +1130,11 @@ TEST_F(CAmRouterMapTest,simpleRoute3DomainsListConnectionFormats_1)
am::am_Sink_s sinkDb;
pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb);
pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb);
- getRoute(false, sourceDb, sinkDb, listRoutes);
+ getRoute(false, true, sourceDb, sinkDb, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0]));
}
-
//test that checks 3 domains, one sink one source, longer lists of connectionformats.
TEST_F(CAmRouterMapTest,simpleRoute3DomainsListConnectionFormats)
{
@@ -1287,12 +1292,11 @@ TEST_F(CAmRouterMapTest,simpleRoute3DomainsListConnectionFormats)
am::am_Sink_s sinkDb;
pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb);
pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb);
- getRoute(false, sourceDb, sinkDb, listRoutes);
+ getRoute(false, true, sourceDb, sinkDb, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0]));
}
-
//test that checks 4 domains, one sink and one source but there are 2 routes because there are 2 gateways
TEST_F(CAmRouterMapTest,simpleRoute4Domains2Routes)
{
@@ -1534,7 +1538,7 @@ TEST_F(CAmRouterMapTest,simpleRoute4Domains2Routes)
am::am_Sink_s sinkDb;
pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb);
pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb);
- getRoute(false, sourceDb, sinkDb, listRoutes);
+ getRoute(false, true, sourceDb, sinkDb, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(2), listRoutes.size());
bool containsRoute1 = std::find_if(listRoutes.begin(), listRoutes.end(), [&](const am_Route_s & ref) {
@@ -1702,9 +1706,10 @@ TEST_F(CAmRouterMapTest,simpleRoute3DomainsNoConnection)
pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb);
pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb);
listRoutes.clear();
- getRoute(false, sourceDb, sinkDb, listRoutes);
+ getRoute(false, true, sourceDb, sinkDb, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(0), listRoutes.size());
}
+
//test that checks just 2 domains, one sink one source with only one connection format each
TEST_F(CAmRouterMapTest,simpleRoute2Domains)
{
@@ -1820,7 +1825,7 @@ TEST_F(CAmRouterMapTest,simpleRoute2Domains)
am::am_Sink_s sinkDb;
pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb);
pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb);
- getRoute(false, sourceDb, sinkDb, listRoutes);
+ getRoute(false, true, sourceDb, sinkDb, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0]));
}
@@ -1917,7 +1922,7 @@ TEST_F(CAmRouterMapTest,simpleRoute2DomainsNoMatchConnectionFormats)
am::am_Sink_s sinkDb;
pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb);
pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb);
- getRoute(false, sourceDb, sinkDb, listRoutes);
+ getRoute(false, true, sourceDb, sinkDb, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(0), listRoutes.size());
}
@@ -2076,7 +2081,7 @@ TEST_F(CAmRouterMapTest,simpleRoute3Domains)
pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb);
pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb);
listRoutes.clear();
- getRoute(false, sourceDb, sinkDb, listRoutes);
+ getRoute(false, true, sourceDb, sinkDb, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0]));
}
@@ -2275,7 +2280,7 @@ TEST_F(CAmRouterMapTest,simpleRoute4Domains)
pDatabaseHandler.getSinkInfoDB(sinkID, sinkDb);
pDatabaseHandler.getSourceInfoDB(sourceID, sourceDb);
listRoutes.clear();
- getRoute(false, sourceDb, sinkDb, listRoutes);
+ getRoute(false, true, sourceDb, sinkDb, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0]));
}
@@ -2400,7 +2405,7 @@ TEST_F(CAmRouterMapTest,route1Domain1Source1Sink)
compareRoute.sinkID = sinkID;
compareRoute.sourceID = sourceID;
- getRoute(false, source, sink, listRoutes);
+ getRoute(false, true, source, sink, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0]));
}
@@ -2485,7 +2490,7 @@ TEST_F(CAmRouterMapTest,route1Domain1Source1Converter1Sink)
compareRoute.sinkID = sinkID1;
compareRoute.sourceID = sourceID;
- getRoute(false, source, sink, listRoutes);
+ getRoute(false, true, source, sink, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
ASSERT_TRUE(pCF.compareRoute(compareRoute,listRoutes[0]));
}
@@ -2600,7 +2605,7 @@ TEST_F(CAmRouterMapTest,route1Domain1Source3Converters1Sink)
compareRoute1.sinkID = sinkID;
compareRoute1.sourceID = sourceID;
- getRoute(false, source, sink, listRoutes);
+ getRoute(false, true, source, sink, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(2), listRoutes.size());
ASSERT_TRUE(pCF.compareRoute(compareRoute1,listRoutes[0])||pCF.compareRoute(compareRoute1,listRoutes[1]));
@@ -2665,7 +2670,7 @@ TEST_F(CAmRouterMapTest,route2Domains1Source1Sink)
pDatabaseHandler.getSourceInfoDB(sourceID, source);
std::vector<am_Route_s> listRoutes;
- getRoute(false, source, sink, listRoutes);
+ getRoute(false, true, source, sink, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
am_Route_s compareRoute1;
@@ -2741,7 +2746,7 @@ TEST_F(CAmRouterMapTest,route3Domains1Source1Sink)
std::vector<am_Route_s> listRoutes;
- getRoute(false, source, sink, listRoutes);
+ getRoute(false, true, source, sink, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
am_Route_s compareRoute1;
@@ -2822,7 +2827,7 @@ TEST_F(CAmRouterMapTest,routeSource1Sink2PathThroughConv1Gate1)
std::vector<am_Route_s> listRoutes;
- getRoute(false, source, sink1, listRoutes);
+ getRoute(false, true, source, sink1, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
am_Route_s compareRoute1;
@@ -2834,7 +2839,7 @@ TEST_F(CAmRouterMapTest,routeSource1Sink2PathThroughConv1Gate1)
ASSERT_TRUE(pCF.compareRoute(compareRoute1,listRoutes[0]));
listRoutes.clear();
- getRoute(false, source, sink2, listRoutes);
+ getRoute(false, true, source, sink2, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(0), listRoutes.size());
}
@@ -2900,13 +2905,13 @@ TEST_F(CAmRouterMapTest, routeSource1Sink1PathThroughDomain2)
pDatabaseHandler.getSinkInfoDB(sink1ID, sink1);
pDatabaseHandler.getSourceInfoDB(sourceID, source);
- getRoute(false, source, sink1, listRoutes);
+ getRoute(false, true, source, sink1, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(0), listRoutes.size());
am::am_Sink_s sink2;
pDatabaseHandler.getSinkInfoDB(sink2ID, sink2);
- getRoute(false, source, sink2, listRoutes);
+ getRoute(false, true, source, sink2, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
am_Route_s compareRoute1;
@@ -2993,12 +2998,12 @@ TEST_F(CAmRouterMapTest, routeSource1Sink1PathThroughGate1Conv2Gate2)
std::vector<am_Route_s> listRoutes;
- getRoute(false, source, sink, listRoutes);
+ getRoute(false, true, source, sink, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(0), listRoutes.size());
am::am_Sink_s sink1;
pDatabaseHandler.getSinkInfoDB(sink2ID, sink1);
- getRoute(false, source, sink1, listRoutes);
+ getRoute(false, true, source, sink1, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
am_Route_s compareRoute1;
@@ -3107,12 +3112,12 @@ TEST_F(CAmRouterMapTest, routeSource1Sink1PathThroughConv1Gate1Conv2Gate2)
std::vector<am_Route_s> listRoutes;
- getRoute(false, source, sink, listRoutes);
+ getRoute(false, true, source, sink, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(0), listRoutes.size());
am::am_Sink_s sink2;
pDatabaseHandler.getSinkInfoDB(coSinkID21, sink2);
- pRouter.getRoute(false, source, sink2, listRoutes);
+ getRoute(false, true, source, sink2, listRoutes, 0);
ASSERT_EQ(static_cast<uint>(2), listRoutes.size());
am_Route_s compareRoute1;
@@ -3217,7 +3222,6 @@ TEST_F(CAmRouterMapTest,route3Domains1Source1SinkGwCycles)
ASSERT_TRUE(sinkNode);
std::vector<am_Route_s> listRoutes;
- std::vector<std::vector<CAmRoutingNode*>> resultNodesPath;
am_Route_s compareRoute1;
compareRoute1.sinkID = sink1ID;
@@ -3231,8 +3235,7 @@ TEST_F(CAmRouterMapTest,route3Domains1Source1SinkGwCycles)
ASSERT_TRUE(didMatch); \
}
-#ifdef ROUTING_BUILD_CONNECTIONS
- getAllPaths(*sourceNode, *sinkNode, listRoutes, resultNodesPath, true);
+ getAllPaths(*sourceNode, *sinkNode, listRoutes, UINT_MAX, 10);
ASSERT_EQ(static_cast<uint>(9), listRoutes.size());
compareRoute1.route.clear();
@@ -3303,19 +3306,169 @@ TEST_F(CAmRouterMapTest,route3Domains1Source1SinkGwCycles)
compareRoute1.route.push_back({source1ID, gw5SinkID, domain1ID, CF_GENIVI_STEREO});
compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_STEREO});
DO_ASSERT()
-#else
+
+ listRoutes.clear();
+
+ getAllPaths(*sourceNode, *sinkNode, listRoutes, 1, 10);
+ ASSERT_EQ(static_cast<uint>(5), listRoutes.size());
+
+ compareRoute1.route.clear();
+ compareRoute1.route.push_back({source1ID, gw2SinkID, domain1ID, CF_GENIVI_STEREO});
+ compareRoute1.route.push_back({gw2SourceID, gw4SinkID, domain2ID, CF_GENIVI_STEREO});
+ compareRoute1.route.push_back({gw4SourceID, gw5SinkID, domain1ID, CF_GENIVI_STEREO});
+ compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_STEREO});
+ DO_ASSERT()
+
+ compareRoute1.route.clear();
+ compareRoute1.route.push_back({source1ID, gw1SinkID, domain1ID, CF_GENIVI_STEREO});
+ compareRoute1.route.push_back({gw1SourceID, gw3SinkID, domain2ID, CF_GENIVI_STEREO});
+ compareRoute1.route.push_back({gw3SourceID, gw5SinkID, domain1ID, CF_GENIVI_STEREO});
+ compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_STEREO});
+ DO_ASSERT()
+
+ compareRoute1.route.clear();
+ compareRoute1.route.push_back({source1ID, gw2SinkID, domain1ID, CF_GENIVI_STEREO});
+ compareRoute1.route.push_back({gw2SourceID, gw3SinkID, domain2ID, CF_GENIVI_STEREO});
+ compareRoute1.route.push_back({gw3SourceID, gw5SinkID, domain1ID, CF_GENIVI_STEREO});
+ compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_STEREO});
+ DO_ASSERT()
+
+ compareRoute1.route.clear();
+ compareRoute1.route.push_back({source1ID, gw1SinkID, domain1ID, CF_GENIVI_STEREO});
+ compareRoute1.route.push_back({gw1SourceID, gw4SinkID, domain2ID, CF_GENIVI_STEREO});
+ compareRoute1.route.push_back({gw4SourceID, gw5SinkID, domain1ID, CF_GENIVI_STEREO});
+ compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_STEREO});
+ DO_ASSERT()
+
compareRoute1.route.clear();
compareRoute1.route.push_back({source1ID, gw5SinkID, domain1ID, CF_GENIVI_STEREO});
compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_STEREO});
-#endif
+ DO_ASSERT()
listRoutes.clear();
- resultNodesPath.clear();
- getAllPaths(*sourceNode, *sinkNode, listRoutes, resultNodesPath, false);
+
+ getAllPaths(*sourceNode, *sinkNode, listRoutes);
ASSERT_EQ(static_cast<uint>(1), listRoutes.size());
DO_ASSERT()
}
+TEST_F(CAmRouterMapTest,route3Domains1Source1SinkGwCycles2)
+{
+ EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK)));
+
+ am_SourceClass_s sourceclass;
+
+ sourceclass.name="sClass";
+ sourceclass.sourceClassID=5;
+
+ ASSERT_EQ(E_OK, pDatabaseHandler.enterSourceClassDB(sourceclass.sourceClassID,sourceclass));
+
+ am_SinkClass_s sinkclass;
+ sinkclass.sinkClassID=5;
+ sinkclass.name="sname";
+
+
+ ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkClassDB(sinkclass,sinkclass.sinkClassID));
+
+ am_domainID_t domain1ID, domain2ID, domain3ID;
+ enterDomainDB("domain1", domain1ID);
+ enterDomainDB("domain2", domain2ID);
+ enterDomainDB("domain3", domain3ID);
+
+ //just make so many cycles as possible
+ std::vector<am_CustomConnectionFormat_t> cfStereo;
+ cfStereo.push_back(CF_GENIVI_STEREO);
+ std::vector<am_CustomConnectionFormat_t> cfOther;
+ cfOther.push_back(CF_GENIVI_AUTO);
+ std::vector<am_CustomConnectionFormat_t> cfMono;
+ cfMono.push_back(CF_GENIVI_MONO);
+
+ am_sourceID_t source1ID;
+ enterSourceDB("source1", domain1ID, cfMono, source1ID);
+ am_sinkID_t gw1SinkID;
+ enterSinkDB("gw1Sink", domain1ID, cfStereo, gw1SinkID);
+ am_sinkID_t gw2SinkID;
+ enterSinkDB("gw2Sink", domain1ID, cfMono, gw2SinkID);
+ am_sourceID_t gw3SourceID;
+ enterSourceDB("gw3Source", domain1ID, cfStereo, gw3SourceID);
+ am_sourceID_t gw4SourceID;
+ enterSourceDB("gw4Source", domain1ID, cfStereo, gw4SourceID);
+ am_sinkID_t gw5SinkID;
+ enterSinkDB("gw5Sink", domain1ID, cfStereo, gw5SinkID);
+
+ am_sourceID_t gw1SourceID;
+ enterSourceDB("gw1Source", domain2ID, cfStereo, gw1SourceID);
+ am_sourceID_t gw2SourceID;
+ enterSourceDB("gw2Source", domain2ID, cfStereo, gw2SourceID);
+ am_sinkID_t gw3SinkID;
+ enterSinkDB("gw3Sink", domain2ID, cfStereo, gw3SinkID);
+ am_sinkID_t gw4SinkID;
+ enterSinkDB("gw4Sink", domain2ID, cfStereo, gw4SinkID);
+
+ am_sourceID_t gw5SourceID;
+ enterSourceDB("gw5Source", domain3ID, cfOther, gw5SourceID);
+ am_sinkID_t sink1ID;
+ enterSinkDB("sink1", domain3ID, cfOther, sink1ID);
+
+ std::vector<bool> matrixT;
+ matrixT.push_back(true);
+ std::vector<bool> matrixF;
+ matrixF.push_back(false);
+
+ am_gatewayID_t gateway1ID;
+ enterGatewayDB("gateway1", domain2ID, domain1ID, cfStereo, cfStereo, matrixT, gw1SourceID, gw1SinkID, gateway1ID);
+ am_gatewayID_t gateway2ID;
+ enterGatewayDB("gateway2", domain2ID, domain1ID, cfStereo, cfMono, matrixT, gw2SourceID, gw2SinkID, gateway2ID);
+ am_gatewayID_t gateway3ID;
+ enterGatewayDB("gateway3", domain1ID, domain2ID, cfStereo, cfStereo, matrixT, gw3SourceID, gw3SinkID, gateway3ID);
+ am_gatewayID_t gateway4ID;
+ enterGatewayDB("gateway4", domain1ID, domain2ID, cfStereo, cfStereo, matrixT, gw4SourceID, gw4SinkID, gateway4ID);
+ am_gatewayID_t gateway5ID;
+ enterGatewayDB("gateway5", domain3ID, domain1ID, cfOther, cfStereo, matrixT, gw5SourceID, gw5SinkID, gateway5ID);
+
+ pRouter.load(false);
+
+ CAmRoutingNode* sourceNode = pRouter.sourceNodeWithID(source1ID);
+ CAmRoutingNode* sinkNode = pRouter.sinkNodeWithID(sink1ID);
+
+ ASSERT_TRUE(sourceNode);
+ ASSERT_TRUE(sinkNode);
+
+ std::vector<am_Route_s> listRoutes;
+
+ am_Route_s compareRoute1;
+ compareRoute1.sinkID = sink1ID;
+ compareRoute1.sourceID = source1ID;
+
+#define DO_ASSERT() \
+ {\
+ bool didMatch = false; \
+ for(auto it = listRoutes.begin(); it!=listRoutes.end(); it++) \
+ didMatch|=pCF.compareRoute(compareRoute1,*it); \
+ ASSERT_TRUE(didMatch); \
+ }
+
+ getRoute(false, false, source1ID, sink1ID, listRoutes, 0, 10);
+ ASSERT_EQ(static_cast<uint>(0), listRoutes.size());
+
+ getRoute(false, false, source1ID, sink1ID, listRoutes, 1, 10);
+ ASSERT_EQ(static_cast<uint>(2), listRoutes.size());
+
+ compareRoute1.route.clear();
+ compareRoute1.route.push_back({source1ID, gw2SinkID, domain1ID, CF_GENIVI_MONO});
+ compareRoute1.route.push_back({gw2SourceID, gw4SinkID, domain2ID, CF_GENIVI_STEREO});
+ compareRoute1.route.push_back({gw4SourceID, gw5SinkID, domain1ID, CF_GENIVI_STEREO});
+ compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_AUTO});
+ DO_ASSERT()
+
+ compareRoute1.route.clear();
+ compareRoute1.route.push_back({source1ID, gw2SinkID, domain1ID, CF_GENIVI_MONO});
+ compareRoute1.route.push_back({gw2SourceID, gw3SinkID, domain2ID, CF_GENIVI_STEREO});
+ compareRoute1.route.push_back({gw3SourceID, gw5SinkID, domain1ID, CF_GENIVI_STEREO});
+ compareRoute1.route.push_back({gw5SourceID, sink1ID, domain3ID, CF_GENIVI_AUTO});
+ DO_ASSERT()
+}
+
TEST_F(CAmRouterMapTest,route3Domains1Source3Gateways3Convertres1Sink)
{
EXPECT_CALL(pMockControlInterface,getConnectionFormatChoice(_,_,_,_,_)).WillRepeatedly(DoAll(returnConnectionFormat(), Return(E_OK)));
@@ -3403,7 +3556,7 @@ TEST_F(CAmRouterMapTest,route3Domains1Source3Gateways3Convertres1Sink)
std::vector<am_Route_s> listRoutes;
- getRoute(false, source, sink, listRoutes);
+ getRoute(false, true, source, sink, listRoutes);
ASSERT_EQ(static_cast<uint>(4), listRoutes.size());
am_Route_s compareRoute1;
@@ -3519,7 +3672,7 @@ TEST_F(CAmRouterMapTest, routeTunerHeadphonePathThroughGWPlus2OtherSinks)
pDatabaseHandler.getSourceInfoDB(tunerID, source);
std::vector<am_Route_s> listRoutes;
- getRoute(false, source, sink, listRoutes);
+ getRoute(false, true, source, sink, listRoutes);
ASSERT_EQ(listRoutes.size(), static_cast<uint>(1));
am_Route_s compareRoute1;
@@ -3536,7 +3689,7 @@ TEST_F(CAmRouterMapTest, routeTunerHeadphonePathThroughGWPlus2OtherSinks)
am::am_Sink_s sink2;
pDatabaseHandler.getSinkInfoDB(rseHeadphoneID, sink2);
pDatabaseHandler.getSourceInfoDB(gwSourceID1, gwSource);
- getRoute(false, gwSource, sink2, listRoutes);
+ getRoute(false, true, gwSource, sink2, listRoutes);
ASSERT_GT(listRoutes.size(), static_cast<uint>(0));
am_Route_s compareRoute2;
diff --git a/AudioManagerCore/test/AmRouterMapTest/CAmRouterMapTest.h b/AudioManagerCore/test/AmRouterMapTest/CAmRouterMapTest.h
index 65ff97b..2fc7a46 100644
--- a/AudioManagerCore/test/AmRouterMapTest/CAmRouterMapTest.h
+++ b/AudioManagerCore/test/AmRouterMapTest/CAmRouterMapTest.h
@@ -94,13 +94,9 @@ public:
const am_sourceID_t & sourceID,
const am_sinkID_t & sinkID,
am_converterID_t & converterID);
- void getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s>& returnList);
- void getRoute(const bool onlyfree, const am_Source_s & aSource, const am_Sink_s & aSink, std::vector<am_Route_s> & listRoutes);
- void getAllPaths(CAmRoutingNode & aSource,
- CAmRoutingNode & aSink,
- std::vector<am_Route_s> & resultPath,
- std::vector<std::vector<CAmRoutingNode*>> & resultNodesPath,
- const bool includeCycles);
+ void getRoute(const bool onlyfree, const bool shouldReload, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector<am_Route_s>& returnList, const unsigned countCycles=0, const unsigned pathsCount=MAX_ROUTING_PATHS);
+ void getRoute(const bool onlyfree, const bool shouldReload, const am_Source_s & aSource, const am_Sink_s & aSink, std::vector<am_Route_s> & listRoutes, const unsigned countCycles=0, const unsigned pathsCount=MAX_ROUTING_PATHS);
+ void getAllPaths(CAmRoutingNode & aSource, CAmRoutingNode & aSink, std::vector<am_Route_s> & resultPath, const unsigned countCycles=0, const unsigned pathsCount=MAX_ROUTING_PATHS);
};
}