#include "manetGraph.h"
#include <protoDebug.h>
#include <new>
NetGraph::Cost::Cost()
{
}
NetGraph::Cost::~Cost()
{
}
NetGraph::Link::Link()
{
}
NetGraph::Link::~Link()
{
}
void NetGraph::Link::SetCost(const Cost& cost)
{
AccessCost() = cost;
}
NetGraph::Interface::Interface(Node& theNode, const ProtoAddress& addr)
: node(&theNode),graph(NULL),default_addr_item(addr), name_ptr(NULL)
{
addr_list.InsertItem(default_addr_item);
}
NetGraph::Interface::Interface(Node& theNode)
: node(&theNode), graph(NULL), default_addr_item(PROTO_ADDR_NONE), name_ptr(NULL)
{
}
NetGraph::Interface::~Interface()
{
if(graph != NULL) graph->RemoveInterface(*this);
Cleanup(); if (!addr_list.IsEmpty())
{
node->RemoveInterface(*this);
addr_list.RemoveItem(default_addr_item);
}
else if (NULL != name_ptr)
{
node->RemoveInterface(*this);
}
if (NULL != name_ptr) delete[] name_ptr;
}
bool NetGraph::Interface::SetName(const char* theName)
{
int length = strlen(theName);
char* namePtr = new char[length+1];
namePtr[length] = '\0';
bool reattach = false; if (NULL == namePtr)
{
PLOG(PL_ERROR,"NetGraph::Interface::SetName(): new name_ptr error: %s\n", GetErrorString());
return false;
}
if (NULL != name_ptr)
{
if (addr_list.IsEmpty())
{
reattach = true;
node->RemoveInterface(*this); if (NULL != graph)
graph->SuspendInterface(*this); }
delete[] name_ptr; }
name_ptr = namePtr;
strcpy(name_ptr, theName);
if (addr_list.IsEmpty() && reattach)
{
if (NULL != graph) {
if (!graph->ResumeInterface(*this))
{
PLOG(PL_ERROR,"NetGraph::Interface::SetName() error: unable to reattach interface to graph: %s\n", GetErrorString());
graph->RemoveInterface(*this);
return false;
}
}
if (!node->AddInterface(*this))
{
PLOG(PL_ERROR,"NetGraph::Interface::SetName() error: unable to add interface to node: %s\n", GetErrorString());
delete[] name_ptr;
name_ptr = NULL;
return false;
}
}
return true;
}
void NetGraph::Interface::ClearName()
{
if (NULL != name_ptr)
{
if (addr_list.IsEmpty())
{
node->RemoveInterface(*this);
if (NULL != graph) graph->RemoveInterface(*this); }
delete[] name_ptr;
name_ptr = NULL;
}
}
bool NetGraph::Interface::AddAddress(const ProtoAddress& theAddress)
{
if (addr_list.IsEmpty())
{
if (NULL != name_ptr)
{
node->RemoveInterface(*this);
if (NULL != graph)
graph->SuspendInterface(*this); }
default_addr_item.SetAddress(theAddress);
if (NULL != graph) {
if (!graph->ResumeInterface(*this))
{
PLOG(PL_ERROR, "NetGraph::Interface::AddAddress() error: failed to add interface to graph\n");
default_addr_item.SetAddress(PROTO_ADDR_NONE);
return false;
}
if (!graph->AddInterfaceAddress(*this, theAddress))
{
PLOG(PL_ERROR, "NetGraph::Interface::AddAddress() error: failed to add address to graph\n");
graph->RemoveInterface(*this);
default_addr_item.SetAddress(PROTO_ADDR_NONE);
return false;
}
}
if (!node->AddInterface(*this))
{
PLOG(PL_ERROR, "NetGraph::Interface::AddAddress() error: failed to add interface to node\n");
if (NULL != graph) graph->RemoveInterface(*this); default_addr_item.SetAddress(PROTO_ADDR_NONE);
return false;
}
}
else if (addr_list.Insert(theAddress))
{
if (!node->AddExtraInterfaceAddress(*this, theAddress))
{
PLOG(PL_ERROR, "NetGraph::Interface::AddAddress() error: failed to add address to node\n");
RemoveAddress(theAddress);
return false;
}
if (NULL != graph)
{
if (!graph->AddInterfaceAddress(*this, theAddress))
{
PLOG(PL_ERROR, "NetGraph::Interface::AddAddress() error: failed to add address to graph\n");
RemoveAddress(theAddress);
return false;
}
}
}
else
{
PLOG(PL_ERROR, "NetGraph::Interface::AddAddress() error: %s\n", GetErrorString());
return false;
}
return true;
}
bool NetGraph::Interface::RemoveAddress(const ProtoAddress& theAddress)
{
#ifdef PROTO_DEBUG
ASSERT(Contains(theAddress)); #else
if (!Contains(theAddress)) return false;
#endif
if (theAddress.HostIsEqual(default_addr_item.GetAddress()))
{
node->RemoveInterface(*this);
if (NULL != graph)
{
addr_list.RemoveItem(default_addr_item);
if (addr_list.IsEmpty() && (NULL == name_ptr))
{
addr_list.InsertItem(default_addr_item);
if (!node->AddInterface(*this))
PLOG(PL_ERROR, "NetGraph::Interface::RemoveAddress() error: failed to reattach interface to node\n");
return false;
}
addr_list.InsertItem(default_addr_item);
graph->SuspendInterface(*this); }
addr_list.RemoveItem(default_addr_item);
if (addr_list.IsEmpty())
{
default_addr_item.SetAddress(PROTO_ADDR_NONE);
if (NULL != name_ptr)
{
if (NULL != graph)
{
if (!graph->ResumeInterface(*this))
{
PLOG(PL_ERROR, "NetGraph::Interface::RemoveAddress() error: failed to reinsert interface into graph\n");
if (!node->AddInterface(*this)) PLOG(PL_ERROR, "NetGraph::Interface::RemoveAddress() error: failed to reattach interface to node\n");
return false;
}
graph->RemoveInterfaceAddress(theAddress);
}
if (!node->AddInterface(*this))
{
PLOG(PL_ERROR, "NetGraph::Interface::RemoveAddress() error: failed to reattach interface to node\n");
if (NULL != graph) graph->RemoveInterface(*this); return false; }
}
else
{
if (NULL != graph) graph->RemoveInterface(*this); }
}
else
{
ProtoAddressList::Item* rootItem = addr_list.RemoveRootItem();
default_addr_item = *rootItem;
delete rootItem;
addr_list.InsertItem(default_addr_item);
if (NULL != graph)
{
if (!graph->ResumeInterface(*this))
{
PLOG(PL_ERROR, "NetGraph::Interface::RemoveAddress() error: failed to reinsert interface into graph\n");
if (!node->AddInterface(*this)) PLOG(PL_ERROR, "NetGraph::Interface::RemoveAddress() error: failed to reattach interface to node\n");
return false;
}
graph->RemoveInterfaceAddress(theAddress);
}
if (!node->AddInterface(*this))
{
PLOG(PL_ERROR, "NetGraph::Interface::RemoveAddress() error: failed to reattach interface to node\n");
if (NULL != graph) graph->RemoveInterface(*this); return false; }
}
}
else
{
addr_list.Remove(theAddress);
node->RemoveExtraInterfaceAddress(theAddress);
if (NULL != graph) graph->RemoveInterfaceAddress(theAddress);
}
return true;
}
bool NetGraph::Interface::ChangeNode(Node& theNode)
{
ASSERT(NULL != node);
node->RemoveInterface(*this);
node = &theNode;
if(!theNode.AddInterface(*this))
{
PLOG(PL_ERROR, "NetGraph::Interface::SetNode: error: AddInterface returned false\n");
return false;
}
return true;
}
NetGraph::AdjacencyIterator::AdjacencyIterator(Interface& theInterface)
: ProtoGraph::AdjacencyIterator(theInterface)
{
}
NetGraph::AdjacencyIterator::~AdjacencyIterator()
{
}
NetGraph::Interface::SimpleList::SimpleList(ItemPool* itemPool)
: Vertice::SimpleList(itemPool)
{
}
NetGraph::Interface::SimpleList::~SimpleList()
{
}
NetGraph::Interface::SimpleList::Iterator::Iterator(const SimpleList& theList)
: ProtoGraph::Vertice::SimpleList::Iterator(theList)
{
}
NetGraph::Interface::SimpleList::Iterator::~Iterator()
{
}
NetGraph::Interface::SortedList::SortedList(ItemPool* itemPool)
: Vertice::SortedList(itemPool)
{
}
NetGraph::Interface::SortedList::~SortedList()
{
}
NetGraph::Interface::SortedList::Iterator::Iterator(SortedList& theList)
: ProtoGraph::Vertice::SortedList::Iterator(theList)
{
}
NetGraph::Interface::SortedList::Iterator::~Iterator()
{
}
NetGraph::Interface::PriorityQueue::Item::Item()
: prev_hop(NULL), next_hop_link(NULL)
{
}
NetGraph::Interface::PriorityQueue::Item::~Item()
{
}
NetGraph::Interface::PriorityQueue::ItemFactory::ItemFactory()
{
}
NetGraph::Interface::PriorityQueue::ItemFactory::~ItemFactory()
{
Destroy();
}
NetGraph::Interface::PriorityQueue::Item* NetGraph::Interface::PriorityQueue::ItemFactory::GetItem()
{
Item* item = static_cast<PriorityQueue::Item*>(item_pool.QueueStatePool::Get());
if (NULL == item) item = CreateItem();
if (NULL == item)
PLOG(PL_ERROR, "NetGraph::Interface::PriorityQueue::ItemFactory::GetItem() CreateItem() error: %s\n",
GetErrorString());
return item;
}
NetGraph::Interface::PriorityQueue::PriorityQueue(PriorityQueue::ItemFactory& itemFactory)
: item_factory(itemFactory)
{
}
NetGraph::Interface::PriorityQueue::~PriorityQueue()
{
Empty();
item_factory.Destroy();
}
bool NetGraph::Interface::PriorityQueue::Insert(Interface& iface, const Cost& cost)
{
Item* item = item_factory.GetItem();
if (NULL == item)
{
PLOG(PL_ERROR, "NetGraph::Interface::PriorityQueue::Insert() error: couldn't allocate item\n");
return false;
}
item->SetCost(cost);
Associate(iface, *item);
InsertItem(*item);
return true;
}
void NetGraph::Interface::PriorityQueue::Adjust(Interface& iface, const Cost& newCost)
{
Item* item = static_cast<Item*>(GetQueueState(iface));
ASSERT(item != NULL);
RemoveItem(*item);
item->SetCost(newCost);
InsertItem(*item);
}
bool NetGraph::Interface::PriorityQueue::AdjustDownward(Interface& iface, const Cost& newCost, const Interface* newPrevHop)
{
Item* item = static_cast<Item*>(GetQueueState(iface));
ASSERT(item != NULL);
if (newCost < item->GetCost())
{
RemoveItem(*item);
item->SetCost(newCost);
InsertItem(*item);
return true;
}
else
{
return false;
}
}
bool NetGraph::Interface::PriorityQueue::AdjustUpward(Interface& iface, const Cost& newCost)
{
Item* item = static_cast<Item*>(GetQueueState(iface));
ASSERT(item != NULL);
if (newCost > item->GetCost())
{
RemoveItem(*item);
item->SetCost(newCost);
InsertItem(*item);
return true;
}
else
{
return false;
}
}
bool NetGraph::Interface::PriorityQueue::Append(Interface& iface)
{
Item* item = item_factory.GetItem();
if (NULL == item)
{
PLOG(PL_ERROR, "NetGraph::Interface::PriorityQueue::Insert() error: couldn't allocate item\n");
return false;
}
Associate(iface, *item);
SortedList::AppendItem(*item);
return true;
}
NetGraph::Interface::PriorityQueue::Iterator::Iterator(PriorityQueue& theQueue)
: SortedList::Iterator(theQueue)
{
}
NetGraph::Interface::PriorityQueue::Iterator::~Iterator()
{
}
const char* NetGraph::Interface::GetVerticeKey() const
{
if (addr_list.IsEmpty())
return name_ptr;
else
return default_addr_item.GetAddress().GetRawHostAddress();
}
unsigned int NetGraph::Interface::GetVerticeKeysize() const
{
if (addr_list.IsEmpty())
{
if (NULL != name_ptr)
{
unsigned int nameSize = strlen(name_ptr);
if (0 == (nameSize & 0x01)) nameSize += 1; return (nameSize << 3);
}
else
{
return 0;
}
}
else
{
return (default_addr_item.GetAddress().GetLength() << 3);
}
}
NetGraph::Node::Node()
: iface_list(true), default_interface_ptr(NULL)
{
}
NetGraph::Node::~Node()
{
Interface* iface;
while (NULL != (iface = static_cast<Interface*>(iface_list.RemoveHead())))
{
delete iface;
}
}
void NetGraph::Node::Consume(Node& foodNode)
{
Interface* iface;
while(NULL != (iface= foodNode.GetDefaultInterface()))
{
iface->ChangeNode(*this);
}
}
bool NetGraph::Node::AddInterface(Interface& iface, bool makeDefault)
{
if(iface_list.IsEmpty()) makeDefault = true;
if(!iface_list.Insert(iface))
{
PLOG(PL_ERROR, "NetGraph::Node::AddInterface() error: Insert failed on the iface_list!\n");
return false;
}
ProtoAddressList::Iterator iterator(iface.GetAddressList());
ProtoAddress addr;
while(iterator.GetNextAddress(addr))
{
if (addr.HostIsEqual(iface.GetDefaultAddress())) continue; if(!extra_addr_list.Insert(addr, &iface))
{
PLOG(PL_ERROR, "NetGraph::Node::AddInterface() error: appending %s to the addr_list?!\n",addr.GetHostString());
RemoveInterface(iface);
return false;
}
}
if (makeDefault) default_interface_ptr = &iface;
return true;
}
void NetGraph::Node::RemoveInterface(Interface& iface)
{
iface_list.Remove(iface);
ProtoAddressList::Iterator iterator(iface.GetAddressList());
ProtoAddress addr;
while(iterator.GetNextAddress(addr))
extra_addr_list.Remove(addr);
if (&iface == default_interface_ptr)
default_interface_ptr = (NetGraph::Interface*)(iface_list.GetRoot());
}
bool NetGraph::Node::IsSymmetricNeighbor(Node& node)
{
NetGraph::Node::InterfaceIterator it(*this);
NetGraph::Interface* interface = it.GetNextInterface();
while(NULL != interface)
{
NetGraph::Node::InterfaceIterator it2(node);
NetGraph::Interface* interface2 = it2.GetNextInterface();
while(NULL != interface2)
{
if(interface->HasLinkTo(*interface2) &&
interface2->HasLinkTo(*interface))
{
return true;
}
interface2 = it2.GetNextInterface();
}
interface = it.GetNextInterface();
}
return false;
}
NetGraph::Interface* NetGraph::Node::FindInterface(const ProtoAddress& addr) const
{
Interface* iface = static_cast<Interface*>(iface_list.Find(addr.GetRawHostAddress(), addr.GetLength() << 3));
if (NULL == iface) iface = (Interface*)(extra_addr_list.GetUserData(addr));
return iface;
}
NetGraph::Interface* NetGraph::Node::FindInterfaceByName(const char* theName)
{
int nameSize = strlen(theName);
if (0 == (nameSize & 0x01)) nameSize++; nameSize <<= 3;
NetGraph::Interface* iface = static_cast<Interface*>(iface_list.Find(theName, nameSize));
if (NULL == iface)
{
InterfaceIterator iterator(*this);
while (NULL != (iface = iterator.GetNextInterface()))
{
const char* ifaceName = iface->GetName();
if ((NULL != ifaceName) && (0 == strcmp(ifaceName, theName)))
break;
}
}
return iface;
}
NetGraph::Interface* NetGraph::Node::FindInterfaceByString(const char* theString)
{
NetGraph::Interface* iface = FindInterfaceByName(theString);
if(NULL == iface)
{
ProtoAddress addr;
addr.ResolveFromString(theString);
if(addr.IsValid())
{
iface = FindInterface(addr);
}
}
return iface;
}
bool NetGraph::Node::SetDefaultInterface(Interface& iface)
{
if (iface.GetAddress().IsValid() || (NULL != iface.GetName()))
{
default_interface_ptr = &iface;
return true;
}
else
{
PLOG(PL_ERROR,"NetGraph::Node::SetDefaultInterface() error: iface has no address or name!\n");
return false;
}
}
NetGraph::Node::InterfaceIterator::InterfaceIterator(Node& node)
: ProtoSortedTree::Iterator(node.iface_list)
{
}
NetGraph::Node::InterfaceIterator::~InterfaceIterator()
{
}
NetGraph::Node::NeighborIterator::NeighborIterator(Node& node)
: iface_iterator(node), adj_iterator(*node.GetDefaultInterface())
{
Reset();
}
NetGraph::Node::NeighborIterator::~NeighborIterator()
{
}
void NetGraph::Node::NeighborIterator::Reset()
{
iface_iterator.Reset();
Interface* firstLocalIface = iface_iterator.GetNextInterface();
if (NULL != firstLocalIface)
{
adj_iterator.~AdjacencyIterator();
new (&adj_iterator) AdjacencyIterator(*firstLocalIface);
}
}
NetGraph::Interface* NetGraph::Node::NeighborIterator::GetNextNeighborInterface()
{
if (iface_iterator.HasEmptyList()) return NULL;
Interface* iface = adj_iterator.GetNextAdjacency();
if (NULL == iface)
{
Interface* nextLocalInterface;
while (NULL != (nextLocalInterface = iface_iterator.GetNextInterface()))
{
adj_iterator.~AdjacencyIterator();
new (&adj_iterator) AdjacencyIterator(*nextLocalInterface);
iface = adj_iterator.GetNextAdjacency();
if (NULL != iface) break;
}
}
return iface;
}
NetGraph::Link* NetGraph::Node::NeighborIterator::GetNextNeighborLink()
{
if (iface_iterator.HasEmptyList()) return NULL;
Link* link = adj_iterator.GetNextAdjacencyLink();
if (NULL == link)
{
Interface* nextLocalInterface;
while (NULL != (nextLocalInterface = iface_iterator.GetNextInterface()))
{
adj_iterator.~AdjacencyIterator();
new (&adj_iterator) AdjacencyIterator(*nextLocalInterface);
link = adj_iterator.GetNextAdjacencyLink();
if (NULL != link) break;
}
}
return link;
}
NetGraph::NetGraph()
{
}
NetGraph::~NetGraph()
{
}
bool NetGraph::InsertNode(Node& node, Interface* iface)
{
if (NULL != iface)
{
if (node.Contains(*iface))
{
return InsertInterface(*iface);
}
else
{
PLOG(PL_ERROR, "NetGraph::InsertNode() error: iface doesn't belong to node!\n");
return false;
}
}
else
{
bool hasIface = false;
Node::InterfaceIterator it(node);
while (NULL != (iface = it.GetNextInterface()))
{
hasIface = true;
if (!InsertInterface(*iface))
{
PLOG(PL_ERROR, "NetGraph::InsertNode() error: failed to add iface to graph!\n");
RemoveNode(node);
return false;
}
}
if (!hasIface)
{
PLOG(PL_ERROR, "NetGraph::InsertNode() error: node has no interfaces?!\n");
return false;
}
return true;
}
}
void NetGraph::RemoveNode(Node& node, Interface* iface)
{
if (NULL == iface)
{
Node::InterfaceIterator it(node);
Interface* iface;
while (NULL != (iface = it.GetNextInterface()))
{
RemoveInterface(*iface);
}
}
else
{
RemoveInterface(*iface);
}
}
bool NetGraph::InsertInterface(Interface& iface)
{
if (!iface.GetAddress().IsValid() && (NULL == iface.GetName()))
{
PLOG(PL_ERROR, "NetGraph::InsertInterface() error: iface has no address or name!\n");
return false;
}
if (NULL != iface.graph) iface.graph->RemoveInterface(iface);
if (ProtoGraph::InsertVertice(iface))
{
ProtoAddressList::Iterator iterator(iface.GetAddressList());
ProtoAddress addr;
while(iterator.GetNextAddress(addr))
{
if(!addr_list.Insert(addr, &iface))
{
PLOG(PL_ERROR, "NetGraph::InsertInterface() error: cannot add address %s to the netgraph addr_list\n",addr.GetHostString());
RemoveInterface(iface);
return false;
}
}
iface.graph = this;
}
return true;
}
void NetGraph::RemoveInterface(Interface& iface)
{
ProtoAddressList::Iterator iterator(iface.GetAddressList());
ProtoAddress addr;
while(iterator.GetNextAddress(addr)) addr_list.Remove(addr);
if (vertice_list.Contains(iface)) RemoveVertice(iface);
iface.graph = NULL;
}
NetGraph::Interface* NetGraph::FindInterfaceByName(const char* theName)
{
if (NULL == theName) return NULL;
unsigned int nameSize = strlen(theName);
if (0 == (nameSize & 0x01)) nameSize++;
nameSize <<= 3;
Interface* iface = static_cast<Interface*>(vertice_list.FindVertice(theName, nameSize));
if (NULL == iface)
{
InterfaceIterator iterator(*this);
while(NULL != (iface = iterator.GetNextInterface()))
{
const char* ifaceName = iface->GetName();
if ((NULL != ifaceName) && (0 == strcmp(ifaceName,theName))) return iface;
}
}
return iface;
}
NetGraph::Interface* NetGraph::FindInterfaceByString(const char* theString)
{
NetGraph::Interface* iface = FindInterfaceByName(theString);
if(NULL == iface)
{
ProtoAddress addr;
addr.ResolveFromString(theString);
if(addr.IsValid())
{
iface = FindInterface(addr);
}
}
return iface;
}
NetGraph::Link* NetGraph::Connect(Interface& srcIface, Interface& dstIface, const Cost& cost)
{
Link* link = srcIface.GetLinkTo(dstIface);
if (NULL != link)
{
PLOG(PL_WARN, "NetGraph::Connect() error: srcIface -> dstIface already connected\n");
return Reconnect(srcIface, dstIface, cost);
}
link = static_cast<Link*>(GetEdge());
if (NULL == link)
{
PLOG(PL_ERROR, "NetGraph::Connect() error: unable to allocate link\n");
return NULL;
}
link->SetCost(cost);
ProtoGraph::Connect(srcIface, dstIface, *link);
return link;
}
bool NetGraph::Connect(Interface& srcIface, Interface& dstIface, const Cost& cost, bool duplex)
{
Link* link = Connect(srcIface, dstIface, cost);
if (!duplex) return (NULL != link);
if (NULL == link)
{
PLOG(PL_ERROR, "NetGraph::Connect() error: unable to allocate forward link\n");
return false;
}
if (NULL == Connect(dstIface, srcIface, cost))
{
PLOG(PL_ERROR, "NetGraph::Connect() error: unable to allocate reverse link\n");
Disconnect(srcIface, dstIface, true);
return false;
}
return true;
}
NetGraph::Link* NetGraph::Reconnect(Interface& srcIface, Interface& dstIface, const Cost& cost)
{
Link* link = srcIface.GetLinkTo(dstIface);
if (NULL == link)
{
PLOG(PL_WARN, "NetGraph::Reconnect() error: srcIface -> dstIface not connected\n");
return NULL;
}
else if (cost == link->GetCost())
{
return link;
}
this->SuspendEdge(srcIface, dstIface, *link);
link->SetCost(cost);
ProtoGraph::Reconnect(srcIface,dstIface,*link);
return link;
}
bool NetGraph::Reconnect(Interface& srcIface, Interface& dstIface, const Cost& cost, bool duplex)
{
Link* link = Reconnect(srcIface, dstIface, cost);
if (!duplex) return (NULL != link);
if (NULL == link)
{
PLOG(PL_ERROR, "NetGraph::Reconnect() error: unable to reconnect forward link\n");
return false;
}
if (NULL == Reconnect(dstIface, srcIface, cost))
{
PLOG(PL_ERROR, "NetGraph::Reconnect() error: unable to reconnect reverse link\n");
Disconnect(srcIface, dstIface, true);
return false;
}
return true;
}
NetGraph::InterfaceIterator::InterfaceIterator(NetGraph& theGraph)
: ProtoGraph::VerticeIterator(static_cast<ProtoGraph&>(theGraph))
{
}
NetGraph::InterfaceIterator::~InterfaceIterator()
{
}
NetGraph::SimpleTraversal::SimpleTraversal(const NetGraph& theGraph,
Interface& startIface,
bool traverseNodes,
bool collapseNodes,
bool depthFirst)
: ProtoGraph::SimpleTraversal(theGraph, startIface, depthFirst),
traverse_nodes(traverseNodes), collapse_nodes(collapseNodes)
{
Reset(true);
}
NetGraph::SimpleTraversal::~SimpleTraversal()
{
}
bool NetGraph::SimpleTraversal::Reset(bool constructor)
{
if (!constructor)
{
if (!ProtoGraph::SimpleTraversal::Reset())
{
PLOG(PL_ERROR, "NetGraph::SimpleTraversal::Reset() error: couldn't enqueue start_vertice\n");
return false;
}
}
if (traverse_nodes && collapse_nodes)
{
Interface& startIface = static_cast<Interface&>(start_vertice);
Node::InterfaceIterator ifaceIterator(startIface.GetNode());
Interface* nextIface;
while (NULL != (nextIface = ifaceIterator.GetNextInterface()))
{
if (static_cast<Interface*>(&start_vertice) == nextIface)
continue;
ASSERT(!nextIface->IsInQueue(queue_visited) && !nextIface->IsInQueue(queue_pending));
if (!AllowLink(startIface, *nextIface, NULL)) continue;
if (depth_first)
queue_pending.Prepend(*nextIface);
else
queue_pending.Append(*nextIface);
}
}
return true;
}
NetGraph::Interface* NetGraph::SimpleTraversal::GetNextInterface(unsigned int* level)
{
Interface* currentIface = static_cast<Interface*>(queue_pending.GetHead());
if (NULL != currentIface)
{
queue_pending.TransferVertice(*currentIface, queue_visited);
Vertice* transAdjacency = NULL; Interface* nextIface;
if (traverse_nodes && !collapse_nodes)
{
Node::InterfaceIterator ifaceIterator(currentIface->GetNode());
while (NULL != (nextIface = ifaceIterator.GetNextInterface()))
{
if (!nextIface->IsInQueue(queue_visited) &&
!nextIface->IsInQueue(queue_pending))
{
if (!AllowLink(*currentIface, *nextIface, NULL)) continue;
if (depth_first)
{
queue_pending.Prepend(*nextIface);
}
else
{
queue_pending.Append(*nextIface);
if (NULL == transAdjacency)
transAdjacency = nextIface;
}
}
}
}
AdjacencyIterator adjacencyIterator(*currentIface);
Link* nextLink;
while (NULL != (nextLink = adjacencyIterator.GetNextAdjacencyLink()))
{
nextIface = nextLink->GetDst();
ASSERT(NULL != nextIface);
if (!nextIface->IsInQueue(queue_visited) &&
!nextIface->IsInQueue(queue_pending))
{
if (!AllowLink(*currentIface, *nextIface, nextLink)) continue;
if (depth_first)
{
queue_pending.Prepend(*nextIface);
}
else
{
queue_pending.Append(*nextIface);
if (NULL == transAdjacency)
transAdjacency = nextIface;
}
if (traverse_nodes && collapse_nodes)
{
Node::InterfaceIterator ifaceIterator(nextIface->GetNode());
Interface* nextCoface;
while (NULL != (nextCoface = ifaceIterator.GetNextInterface()))
{
if (nextCoface == nextIface) continue;
ASSERT(!nextCoface->IsInQueue(queue_visited) && !nextCoface->IsInQueue(queue_pending));
if (depth_first)
queue_pending.Prepend(*nextCoface);
else
queue_pending.Append(*nextCoface);
}
}
}
}
if (NULL == trans_vertice)
{
trans_vertice = transAdjacency;
}
else if (trans_vertice == currentIface)
{
current_level++;
trans_vertice = transAdjacency;
}
if (NULL != level) *level = current_level;
}
return currentIface;
}
NetGraph::DijkstraTraversal::DijkstraTraversal(NetGraph& theGraph,
Interface* startIface)
: manet_graph(theGraph), start_iface(startIface),
queue_pending(static_cast<ItemFactory&>(*this)),
queue_visited(static_cast<ItemFactory&>(*this)),
trans_iface(NULL), current_level(0), dijkstra_completed(false), in_update(false), traverse_nodes(false), reset_required(false)
{
}
NetGraph::DijkstraTraversal::DijkstraTraversal(NetGraph& theGraph,
Node& startNode,
Interface* startIface)
: manet_graph(theGraph), start_iface((NULL != startIface) ? startIface : startNode.GetDefaultInterface()),
queue_pending(static_cast<ItemFactory&>(*this)),
queue_visited(static_cast<ItemFactory&>(*this)),
trans_iface(NULL), current_level(0), dijkstra_completed(false), in_update(false), traverse_nodes(false), reset_required(false)
{
}
NetGraph::DijkstraTraversal::~DijkstraTraversal()
{
queue_pending.Empty();
queue_visited.Empty();
}
void
NetGraph::DijkstraTraversal::TraverseNodes(bool traverse)
{
traverse_nodes = traverse;
}
bool NetGraph::DijkstraTraversal::Reset(Interface* startIface)
{
queue_visited.Empty();
queue_pending.Empty();
Cost& startCost = AccessCostTemp();
startCost.Minimize();
if (NULL != startIface)
start_iface = startIface;
if (NULL != start_iface)
{
if(traverse_nodes)
{
Node::InterfaceIterator ifaceIterator(start_iface->GetNode());
Interface* nextIface;
while (NULL != (nextIface = ifaceIterator.GetNextInterface()))
{
if (!queue_pending.Insert(*nextIface, startCost))
{
PLOG(PL_ERROR, "NetGraph::DijkstraTraversal::Reset() error: couldn't enqueue a start_iface (traverse_nodes)\n");
return false;
}
}
}
else
{
if (!queue_pending.Insert(*start_iface, startCost))
{
PLOG(PL_ERROR, "NetGraph::DijkstraTraversal::Reset() error: couldn't enqueue start_iface\n");
return false;
}
}
dijkstra_completed = false;
}
else
{
dijkstra_completed = true;
}
return true;
}
NetGraph::Interface* NetGraph::DijkstraTraversal::GetNextInterface()
{
Interface* currentIface = queue_pending.GetHead();
if (NULL != currentIface)
{
queue_pending.TransferInterface(*currentIface, queue_visited);
const Cost* currentCost = queue_visited.GetCost(*currentIface);
ASSERT(NULL != currentCost);
AdjacencyIterator linkIterator(*currentIface);
Link* nextLink;
while ((nextLink = linkIterator.GetNextAdjacencyLink()))
{
Interface* nextDst = nextLink->GetDst();
ASSERT(NULL != nextDst);
if (!AllowLink(*currentIface, *nextLink)) continue;
const Cost& linkCost = nextLink->GetCost();
Cost& nextCost = AccessCostTemp();
nextCost = linkCost;
nextCost += *currentCost;
Node::InterfaceIterator ifaceIterator(nextDst->GetNode());
if(traverse_nodes)
nextDst = ifaceIterator.GetNextInterface();
do
{
bool saveState = true;
if(!in_update)
{
if (nextDst->IsInQueue(queue_pending))
{
if (!queue_pending.AdjustDownward(*nextDst, nextCost, currentIface))
saveState = false;
}
else if (!nextDst->IsInQueue(queue_visited))
{
if (!queue_pending.Insert(*nextDst, nextCost))
{
PLOG(PL_ERROR, "NetGraph::DijkstraTraversal::GetNextInterface() error: couldn't enqueue iface\n");
return NULL;
}
}
else
{
saveState = false;
}
}
else {
Interface* prevHopIface;
bool isInVisited = false;
bool isNewIface = false;
Interface::PriorityQueue* queuePtr = &queue_pending;
if(nextDst->IsInQueue(queue_visited))
{
isInVisited = true;
queuePtr = &queue_visited;
}
else if (!nextDst->IsInQueue(queue_pending))
{
isNewIface = true;
}
if(isNewIface)
{
if (!queue_pending.Insert(*nextDst, nextCost))
{
PLOG(PL_ERROR, "NetGraph::DijkstraTraversal::GetNextInterface() error: couldn't enqueue iface\n");
return NULL;
}
}
else if (queuePtr->AdjustDownward(*nextDst, nextCost, currentIface)) {
if(isInVisited)
{
queue_visited.TransferInterface(*nextDst, queue_pending); }
}
else if(NULL != (prevHopIface = queuePtr->GetPrevHop(*nextDst)))
{
bool linkWasUsed = false;
if(traverse_nodes)
{
if (currentIface->GetNode().Contains(*prevHopIface))
linkWasUsed = true;
}
else
{
if (currentIface == prevHopIface)
linkWasUsed = true;
}
if(linkWasUsed)
{
if(queuePtr->AdjustUpward(*nextDst, nextCost))
{
reset_required = true;
saveState = false;
return NULL;
}
else
{
saveState = false;
}
}
else
{
saveState = false;
}
}
else
{
saveState = false;
}
}
if(saveState)
{
if(start_iface->GetNode().Contains(*currentIface))
{
if(nextDst==NULL)
{
}
else
{
}
if(nextLink==NULL)
{
}
else
{
}
if(currentIface==NULL)
{
}
else
{
}
queue_pending.SetRouteInfo(*nextDst, nextLink, currentIface);
}
else
{
if(queue_visited.Contains(*currentIface))
queue_pending.SetRouteInfo(*nextDst, queue_visited.GetNextHopLink(*currentIface), currentIface);
else
queue_pending.SetRouteInfo(*nextDst, queue_pending.GetNextHopLink(*currentIface), currentIface);
}
}
if(traverse_nodes)
nextDst = ifaceIterator.GetNextInterface();
else
nextDst = NULL;
} while (nextDst != NULL);
} }
else
{
dijkstra_completed = true;
}
return currentIface;
}
bool NetGraph::DijkstraTraversal::PrevHopIsValid(Interface& currentIface)
{
ASSERT(start_iface != NULL);
if (!traverse_nodes)
{
if (¤tIface == start_iface)
return true;
}
else
{
if(currentIface.GetNode().Contains(*start_iface))
return true;
}
const Cost* currCostPtr = GetCost(currentIface);
if(currCostPtr == NULL)
return false;
Interface* prevHopIface = NULL;
if(NULL != (prevHopIface = queue_visited.GetPrevHop(currentIface)))
{
const Cost* prevCostPtr = GetCost(*prevHopIface);
if(prevCostPtr == NULL)
return false;
if(!traverse_nodes)
{
Link* linkPtr = prevHopIface->GetLinkTo(currentIface);
if(linkPtr != NULL)
{
if (AllowLink(*prevHopIface, *linkPtr))
{
Cost& sumCost = AccessCostTemp();
sumCost = linkPtr->GetCost();
sumCost += *prevCostPtr;
if(sumCost > *currCostPtr)
{
return false;
}
else if (sumCost < *currCostPtr)
{
return true;
}
else
{
return true;
}
}
}
else
{
return false;
}
}
else
{
ManetNode::NeighborIterator nbIt(prevHopIface->GetNode());
Link* linkPtr = NULL;
while(NULL != (linkPtr = nbIt.GetNextNeighborLink()))
{
Interface* srcPtr = linkPtr->GetSrc();
ASSERT(NULL != srcPtr);
if (!AllowLink(*srcPtr, *linkPtr)) continue;
Interface* dstPtr = linkPtr->GetDst();
if(dstPtr!=NULL)
{
if(currentIface.GetNode().Contains(*dstPtr))
{
Cost& sumCost = AccessCostTemp();
sumCost = linkPtr->GetCost();
sumCost += *prevCostPtr;
if(sumCost <= *currCostPtr)
return true;
if (sumCost == *currCostPtr)
return true;
}
}
}
return false;
}
}
else
{
return false;
}
return true;
}
void NetGraph::DijkstraTraversal::Update(Interface& startIface)
{
if (!dijkstra_completed)
{
Reset();
while (NULL != GetNextInterface());
return;
}
if(!PrevHopIsValid(startIface))
{
Reset();
while (NULL != GetNextInterface());
return;
}
ASSERT(queue_pending.IsEmpty());
in_update = true;
Interface* origStartIfacePtr = start_iface;
start_iface=&startIface;
if(startIface.IsInQueue(queue_visited))
{
if(traverse_nodes)
{
Node::InterfaceIterator ifaceIterator(startIface.GetNode());
Interface* nextIface = NULL;
while (NULL !=(nextIface = ifaceIterator.GetNextInterface()))
queue_visited.TransferInterface(*nextIface, queue_pending);
}
else
{
queue_visited.TransferInterface(startIface, queue_pending);
}
}
else
{
reset_required = true;
}
if(!reset_required)
{
}
Interface *nextIface = GetNextInterface();
if(reset_required)
nextIface = NULL;
while (NULL != nextIface)
{
if(reset_required)
nextIface = NULL;
else
nextIface = GetNextInterface();
}
in_update = false;
start_iface=origStartIfacePtr;
if(reset_required)
{
Reset();
while (NULL != GetNextInterface());
}
}
void NetGraph::DijkstraTraversal::Update(Interface& ifaceA, Interface& ifaceB)
{
const NetGraph::Cost* aCostPtr = GetCost(ifaceA);
const NetGraph::Cost* bCostPtr = GetCost(ifaceB);
if((aCostPtr != NULL) && (bCostPtr != NULL))
{
if(*aCostPtr > *bCostPtr)
{
Link* linkPtr = ifaceB.GetLinkTo(ifaceA);
if(NULL != linkPtr)
{
if (!AllowLink(ifaceB, *linkPtr))
{
Update(ifaceA);
}
else
{
Update(ifaceB);
}
}
else
{
Update(ifaceA);
}
}
else
{
Link* linkPtr = ifaceA.GetLinkTo(ifaceB);
if(NULL != linkPtr)
{
if (!AllowLink(ifaceA, *linkPtr))
{
Update(ifaceB);
}
else
{
Update(ifaceA);
}
}
else
{
Update(ifaceB);
}
}
}
else if(aCostPtr != NULL)
{
Update(ifaceA);
}
else if (bCostPtr != NULL)
{
Update(ifaceB);
}
}
bool NetGraph::DijkstraTraversal::TreeWalkReset()
{
if (!dijkstra_completed)
{
Reset();
while (NULL != GetNextInterface());
}
ASSERT(queue_pending.IsEmpty());
if (NULL != start_iface)
{
if (!queue_pending.Append(*start_iface))
{
PLOG(PL_ERROR, "NetGraph::DijkstraTraversal::TreeWalkReset() error: couldn't append start_iface\n");
return false;
}
}
trans_iface = NULL;
current_level = 0;
return true;
}
NetGraph::Interface* NetGraph::DijkstraTraversal::TreeWalkNext(unsigned int* level)
{
Interface* currentIface = queue_pending.RemoveHead();
if (NULL != currentIface)
{
Link* nextLink;
Link* firstLink = NULL;
if(traverse_nodes)
{
NetGraph::Node::NeighborIterator linkIterator(currentIface->GetNode());
while ((nextLink = linkIterator.GetNextNeighborLink()))
{
Interface* nextDst = nextLink->GetDst();
ASSERT(NULL != nextDst);
if (currentIface == GetPrevHop(*nextDst))
{
if (NULL == firstLink) firstLink = nextLink;
queue_pending.Append(*nextDst);
}
}
}
else
{
AdjacencyIterator linkIterator(*currentIface);
while ((nextLink = linkIterator.GetNextAdjacencyLink()))
{
Interface* nextDst = nextLink->GetDst();
ASSERT(NULL != nextDst);
if (currentIface == GetPrevHop(*nextDst))
{
if (NULL == firstLink) firstLink = nextLink;
queue_pending.Append(*nextDst);
}
}
}
if (NULL == trans_iface)
{
trans_iface = firstLink ? firstLink->GetDst() : NULL;
}
else if (trans_iface == currentIface)
{
trans_iface = firstLink ? firstLink->GetDst() : NULL;
current_level++;
}
if (NULL != level) *level = current_level;
}
return currentIface;
}