Switch to side-by-side view

--- a
+++ b/src/policies/DIF/Routing/DomainRouting/LS/LS.cc
@@ -0,0 +1,262 @@
+/*
+ * LS.cc
+ *
+ *  Created on: Mar 23, 2015
+ *      Author: gaixas1
+ */
+
+#include "DomainRouting/LS/LS.h"
+#include "DomainRouting/Routing.h"
+
+namespace DMRnmsLS {
+
+using namespace DMRnms;
+using namespace std;
+
+
+
+LSUpdate::LSUpdate(const Address &_addr, const string &_domain)
+    :RoutingUpdate(_addr, _domain){}
+
+
+void LSUpdate::addEntry(const std::string & _addr, linksU _neig) {
+    entries[_addr] = _neig;
+}
+void LSUpdate::setEntries(linksSt _entries) {
+    entries = _entries;
+}
+
+linksStIt LSUpdate::entriesBegin() {
+    return entries.begin();
+}
+
+linksStIt LSUpdate::entriesEnd() {
+    return entries.end();
+}
+
+
+LS::LS(Routing * parent, const Address &_nAddr, const string &_domain, const string &_addr)
+    :rModule(parent, _nAddr, _domain, _addr) {
+    scheduledUpdate = false;
+    secId = 1;
+}
+
+bool LS::processUpdate(RoutingUpdate * update){
+    // Cast update to known type
+    LSUpdate * up = dynamic_cast<LSUpdate*>(update);
+    if(up == NULL) { return false; }
+
+    for(linksStIt it = up->entriesBegin(); it != up->entriesEnd(); it++){
+        string node = it->first;
+        if(netState[node].sId < it->second.sId){
+            netState[node] = it->second;
+            changed.insert(node);
+        }
+    }
+
+    if(! changed.empty()) {
+        scheduleUpdate();
+        return true;
+    } else {
+        return false;
+    }
+}
+
+void LS::addFlow(const Address &_nAddr, const std::string &_addr, const unsigned short &_metric){
+    nei[_nAddr] = _metric;
+    neigTable[_addr] = _nAddr;
+
+    changed.insert(myAddr);
+    secId++;
+
+    linksU * myEntry = &(netState[myAddr]);
+    myEntry->sId = secId;
+    myEntry->links[_addr] = _metric;
+
+    scheduleUpdate();
+}
+
+void LS::removeFlow(const Address &_nAddr, const std::string &_addr){
+    nei.erase(_nAddr);
+    neigTable.erase(_addr);
+
+    changed.insert(myAddr);
+    secId++;
+
+    linksU * myEntry = &(netState[myAddr]);
+    myEntry->sId = secId;
+    myEntry->links.erase(_addr);
+
+    scheduleUpdate();
+}
+
+void LS::addAddr(const std::string &_addr){
+    myAddrSet.insert(_addr);
+
+    secId++;
+
+    linksU * myEntry = &(netState[myAddr]);
+    myEntry->sId = secId;
+    myEntry->links[_addr] = 0;
+
+    scheduleUpdate();
+}
+
+void LS::removeAddr(const std::string &_addr){
+    myAddrSet.erase(_addr);
+
+    secId++;
+
+    linksU * myEntry = &(netState[myAddr]);
+    myEntry->sId = secId;
+    myEntry->links.erase(_addr);
+
+    scheduleUpdate();
+}
+
+void LS::setInfMetric(const unsigned short &inf){}
+
+dmNxt LS::getChanges(){
+    dmNxt ret(domain);
+
+    TreeNode t = constructTree();
+    for(TreeNodeIt it = t.chl.begin(); it != t.chl.end(); it++){
+        ret.entries[(*it)->addr] = neigTable[(*it)->addr];
+        addRecursive(ret.entries, neigTable[(*it)->addr], *it);
+    }
+
+    s2A tmp = ret.entries;
+
+    for(s2AIt tIt = currentTable.begin(); tIt != currentTable.end(); tIt++){
+        if(ret.entries[tIt->first] == tIt->second){
+            ret.entries.erase(tIt->first);
+        }
+    }
+
+    currentTable = tmp;
+
+    return ret;
+}
+
+dmNxt LS::getAll() {
+    dmNxt ret(domain);
+
+    TreeNode t = constructTree();
+    for(TreeNodeIt it = t.chl.begin(); it != t.chl.end(); it++){
+        ret.entries[(*it)->addr] = neigTable[(*it)->addr];
+        addRecursive(ret.entries, neigTable[(*it)->addr], *it);
+    }
+
+    currentTable = ret.entries;
+    return ret;
+}
+
+void LS::handleMessage(cMessage *msg){
+    if(msg->isSelfMessage()){
+        //get Changes
+        linksSt _entries = getChangedEntries ();
+
+        //iterate all Neighbour
+        for(neighMetricIt itN = nei.begin(); itN != nei.end(); itN++){
+            //New Update to Neighbour
+            LSUpdate * update = new LSUpdate(itN->first, domain);
+
+            //Populate the update
+            update->setEntries(_entries);
+
+            parent->chSendUpdate(update);
+        }
+
+        changed.clear();
+        scheduledUpdate = false;
+    }
+    delete msg;
+}
+
+
+void LS::scheduleUpdate(){
+    if(!scheduledUpdate){
+        scheduledUpdate = true;
+        scheduleAt(1, new cMessage("Time2Update"));
+    }
+}
+
+
+
+linksSt LS::getChangedEntries () {
+    linksSt ret;
+    for(sSetIt it = changed.begin(); it != changed.end(); it++){
+        ret[*it] = netState[*it];
+    }
+    return ret;
+}
+
+
+TreeNode LS::constructTree() {
+    TreeNode t(myAddr, 0);
+    s2m added;
+    added[myAddr] = 0;
+
+    wMap waiting;
+    s2m * links = &(netState[myAddr].links);
+    for(s2mIt it = links->begin(); it !=links->end(); it++){
+        waiting[it->first] = psT(&t, it->second);
+    }
+
+
+    while(!waiting.empty()){
+        unsigned short min = UINT16_MAX;
+        sList mins;
+
+        for (wMapIt it = waiting.begin(); it != waiting.end(); it++){
+            if(it->second.metric < min){
+                min = it->second.metric;
+                mins.clear();
+            }
+            if(it->second.metric == min){
+                mins.push_back(it->first);
+            }
+        }
+
+        while(!mins.empty()){
+            string addr = mins.back();
+            mins.pop_back();
+
+            psT ps = waiting[addr];
+            waiting.erase(addr);
+
+            TreeNode * nt = new TreeNode(addr, ps.metric);
+            ps.p->chl.insert(nt);
+
+            added[addr] = ps.metric;
+
+            links = &(netState[addr].links);
+
+            for(s2mIt it = links->begin(); it !=links->end(); it++){
+                string daddr = it->first;
+                if(added.find(daddr) == added.end()){
+                    wMapIt eI = waiting.find(daddr);
+                    if(eI == waiting.end()){
+                        waiting[daddr] = psT(nt, ps.metric + it->second);
+                    } else if(eI->second.metric > ps.metric + it->second){
+                        eI->second.metric = ps.metric + it->second;
+                        eI->second.p = nt;
+                    }
+                }
+            }
+        }
+    }
+
+    return t;
+}
+
+void LS::addRecursive(s2A &ret, const Address &next, TreeNode * t) {
+    for(TreeNodeIt it = t->chl.begin(); it != t->chl.end(); it++){
+        ret[(*it)->addr] = next;
+        addRecursive(ret, next, *it);
+    }
+}
+
+
+
+} /* namespace DomainRouting */