Public Member Functions | Protected Member Functions | Protected Attributes

SimpleUnderlayConfigurator Class Reference

Sets up a SimpleNetwork. More...

#include <SimpleUnderlayConfigurator.h>

Inheritance diagram for SimpleUnderlayConfigurator:
UnderlayConfigurator

List of all members.

Public Member Functions

 ~SimpleUnderlayConfigurator ()
virtual TransportAddresscreateNode (NodeType type, bool initialize=false)
 Creates an overlay node.
virtual void preKillNode (NodeType type, TransportAddress *addr=NULL)
 Notifies and schedules overlay nodes for removal.
virtual void migrateNode (NodeType type, TransportAddress *addr=NULL)
 Migrates overlay nodes from one access net to another.
uint32_t getFieldSize ()
uint32_t getFieldDimension ()
uint32_t getSendQueueLenghth ()

Protected Member Functions

void initializeUnderlay (int stage)
 Enables access to the globalHashMap, sets some parameters and adds the initial number of nodes to the network.
void handleTimerEvent (cMessage *msg)
void finishUnderlay ()
 Saves statistics, prints simulation time.
void setDisplayString ()
 Prints statistics.
uint32_t parseCoordFile (const char *nodeCoordinateSource)

Protected Attributes

uint32 nextFreeAddress
 adress of the node that will be created next
std::deque< IPvXAddress > killList
 stores nodes scheduled to be killed
std::set< int > scheduledID
 stores nodeIds to prevent migration of prekilled nodes
uint32_t sendQueueLength
 send queue length of overlay terminals
uint32_t fieldSize
int dimensions
bool fixedNodePositions
bool useIPv6
bool useXmlCoords
const char * nodeCoordinateSource
uint32_t maxCoordinate
std::vector< std::pair
< NodeRecord *, bool > > 
nodeRecordPool
int numCreated
 number of overall created overlay terminals
int numKilled
 number of overall killed overlay terminals

Detailed Description

Sets up a SimpleNetwork.

Adds overlay nodes to the network in init phase and adds/removes/migrates overlay nodes after init phase.

Definition at line 43 of file SimpleUnderlayConfigurator.h.


Constructor & Destructor Documentation

SimpleUnderlayConfigurator::~SimpleUnderlayConfigurator (  ) 

Definition at line 52 of file SimpleUnderlayConfigurator.cc.

{
    for (uint32_t i = 0; i < nodeRecordPool.size(); ++i) {
        //std::cout << (nodeRecordPool[i].second ? "+" : "_");
        delete nodeRecordPool[i].first;
    }
    nodeRecordPool.clear();
}


Member Function Documentation

TransportAddress * SimpleUnderlayConfigurator::createNode ( NodeType  type,
bool  initialize = false 
) [virtual]

Creates an overlay node.

Parameters:
type NodeType of the node to create
initialize are we in init phase?

Implements UnderlayConfigurator.

Definition at line 111 of file SimpleUnderlayConfigurator.cc.

{
    Enter_Method_Silent();
    // derive overlay node from ned
    cModuleType* moduleType = cModuleType::get(type.terminalType.c_str());

    std::string nameStr = "overlayTerminal";
    if (churnGenerator.size() > 1) {
        nameStr += "-" + convertToString<int32_t>(type.typeID);
    }
    cModule* node = moduleType->create(nameStr.c_str(), getParentModule(),
                                       numCreated + 1, numCreated);

    std::string displayString;

    if ((type.typeID > 0) && (type.typeID <= NUM_COLORS)) {
        ((displayString += "i=device/wifilaptop_l,")
                += colorNames[type.typeID - 1]) += ",40;i2=block/circle_s";
    } else {
        displayString = "i=device/wifilaptop_l;i2=block/circle_s";
    }

    node->finalizeParameters();
    node->setDisplayString(displayString.c_str());
    node->buildInside();
    node->scheduleStart(simTime());

    for (int i = 0; i < MAX_STAGE_UNDERLAY + 1; i++) {
        node->callInitialize(i);
    }

    IPvXAddress addr;
    if (useIPv6) {
        addr = IPv6Address(0, nextFreeAddress++, 0, 0);
    } else {
        addr = IPAddress(nextFreeAddress++);
    }

    int chanIndex = intuniform(0, type.channelTypesRx.size() - 1);
    cChannelType* rxChan = cChannelType::find(type.channelTypesRx[chanIndex].c_str());
    cChannelType* txChan = cChannelType::find(type.channelTypesTx[chanIndex].c_str());

    if (!txChan || !rxChan)
         opp_error("Could not find Channel Type. Most likely parameter "
            "channelTypesRx or channelTypes does not match the channels defined in "
             "channels.ned");

    SimpleNodeEntry* entry;

    if (!useXmlCoords) {
        entry = new SimpleNodeEntry(node, rxChan, txChan, sendQueueLength, fieldSize);
    } else {
        // get random unused node
        uint32_t volunteer = intuniform(0, nodeRecordPool.size() - 1);
        uint32_t temp = volunteer;
        while (nodeRecordPool[volunteer].second == false) {
            ++volunteer;
            if (volunteer >= nodeRecordPool.size())
                volunteer = 0;
            // stop with errormessage if no more unused nodes available
            if (temp == volunteer)
                throw cRuntimeError("No unused coordinates left -> "
                    "cannot create any more nodes. "
                    "Provide %s-file with more nodes!\n", nodeCoordinateSource);
        }

         entry = new SimpleNodeEntry(node, rxChan, txChan,
                 sendQueueLength, nodeRecordPool[volunteer].first, volunteer);

        // insert IP-address into noderecord used
        // nodeRecordPool[volunteer].first->ip = addr;
        nodeRecordPool[volunteer].second = false;
    }

    SimpleUDP* simpleUdp = check_and_cast<SimpleUDP*> (node->getSubmodule("udp"));
    simpleUdp->setNodeEntry(entry);
    SimpleTCP* simpleTcp = dynamic_cast<SimpleTCP*> (node->getSubmodule("tcp", 0));
    if (simpleTcp) {
        simpleTcp->setNodeEntry(entry);
    }

    // Add pseudo-Interface to node's interfaceTable
    if (useIPv6) {
        IPv6InterfaceData* ifdata = new IPv6InterfaceData;
        ifdata->assignAddress(addr.get6(),false, 0, 0);
        IPv6InterfaceData::AdvPrefix prefix = {addr.get6(), 64};
        ifdata->addAdvPrefix(prefix);
        InterfaceEntry* e = new InterfaceEntry;
        e->setName("dummy interface");
        e->setIPv6Data(ifdata);
        IPAddressResolver().interfaceTableOf(node)->addInterface(e, NULL);
    }
    else {
        IPv4InterfaceData* ifdata = new IPv4InterfaceData;
        ifdata->setIPAddress(addr.get4());
        ifdata->setNetmask(IPAddress("255.255.255.255"));
        InterfaceEntry* e = new InterfaceEntry;
        e->setName("dummy interface");
        e->setIPv4Data(ifdata);

        IPAddressResolver().interfaceTableOf(node)->addInterface(e, NULL);
    }

    // create meta information
    SimpleInfo* info = new SimpleInfo(type.typeID, node->getId(), type.context);
    info->setEntry(entry);

    //add node to bootstrap oracle
    globalNodeList->addPeer(addr, info);

    // if the node was not created during startup we have to
    // finish the initialization process manually
    if (!initialize) {
        for (int i = MAX_STAGE_UNDERLAY + 1; i < NUM_STAGES_ALL; i++) {
            node->callInitialize(i);
        }
    }

    //show ip...
    //TODO: migrate
    if (fixedNodePositions && ev.isGUI()) {
        node->getDisplayString().insertTag("p");
        node->getDisplayString().setTagArg("p", 0, (long int)(entry->getX() * 5));
        node->getDisplayString().setTagArg("p", 1, (long int)(entry->getY() * 5));
        node->getDisplayString().insertTag("t", 0);
        node->getDisplayString().setTagArg("t", 0, addr.str().c_str());
        node->getDisplayString().setTagArg("t", 1, "l");
    }

    overlayTerminalCount++;
    numCreated++;

    churnGenerator[type.typeID]->terminalCount++;

    TransportAddress *address = new TransportAddress(addr);

    // update display
    setDisplayString();

    return address;
}

void SimpleUnderlayConfigurator::finishUnderlay (  )  [protected, virtual]

Saves statistics, prints simulation time.

Reimplemented from UnderlayConfigurator.

Definition at line 515 of file SimpleUnderlayConfigurator.cc.

{
    // statistics
    recordScalar("Terminals added", numCreated);
    recordScalar("Terminals removed", numKilled);

    if (!isInInitPhase()) {
        struct timeval now, diff;
        gettimeofday(&now, NULL);
        timersub(&now, &initFinishedTime, &diff);
        printf("Simulation time: %li.%06li\n", diff.tv_sec, diff.tv_usec);
    }
}

uint32_t SimpleUnderlayConfigurator::getFieldDimension (  )  [inline]

Definition at line 73 of file SimpleUnderlayConfigurator.h.

{ return dimensions; };

uint32_t SimpleUnderlayConfigurator::getFieldSize (  )  [inline]

Definition at line 72 of file SimpleUnderlayConfigurator.h.

{ return fieldSize; };

uint32_t SimpleUnderlayConfigurator::getSendQueueLenghth (  )  [inline]

Definition at line 74 of file SimpleUnderlayConfigurator.h.

{ return sendQueueLength; };

void SimpleUnderlayConfigurator::handleTimerEvent ( cMessage *  msg  )  [protected, virtual]

Reimplemented from UnderlayConfigurator.

Definition at line 467 of file SimpleUnderlayConfigurator.cc.

{
    Enter_Method_Silent();

    // get next scheduled node and remove it from the kill list
    IPvXAddress addr = killList.back();
    killList.pop_back();

    SimpleNodeEntry* entry = NULL;

    SimpleInfo* info =
            dynamic_cast<SimpleInfo*> (globalNodeList->getPeerInfo(addr));

    if (info != NULL) {
        entry = info->getEntry();
    } else {
        throw cRuntimeError("SimpleUnderlayConfigurator: Trying to kill "
                            "node with unknown TransportAddress!");
    }

    cGate* gate = entry->getUdpIPv4Gate();
    cModule* node = gate->getOwnerModule()->getParentModule();

    if (useXmlCoords) {
        nodeRecordPool[entry->getRecordIndex()].second = true;
    }

    scheduledID.erase(node->getId());
    globalNodeList->killPeer(addr);

    InterfaceEntry* ie = IPAddressResolver().interfaceTableOf(node)->
                                         getInterfaceByName("dummy interface");
    delete ie->ipv4Data();

    node->callFinish();
    node->deleteModule();

    delete msg;
}

void SimpleUnderlayConfigurator::initializeUnderlay ( int  stage  )  [protected, virtual]

Enables access to the globalHashMap, sets some parameters and adds the initial number of nodes to the network.

Parameters:
stage the phase of the initialisation

Implements UnderlayConfigurator.

Definition at line 61 of file SimpleUnderlayConfigurator.cc.

{
    if (stage != MAX_STAGE_UNDERLAY)
        return;

    // fetch some parameters
    fixedNodePositions = par("fixedNodePositions");
    useIPv6 = par("useIPv6Addresses");

    // set maximum coordinates and send queue length
    fieldSize = par("fieldSize");
    sendQueueLength = par("sendQueueLength");

    // get parameter of sourcefile's name
    nodeCoordinateSource = par("nodeCoordinateSource");

    if (std::string(nodeCoordinateSource) != "") {
        // check if exists and process xml-file containing coordinates
        std::ifstream check_for_xml_file(nodeCoordinateSource);
        if (check_for_xml_file) {
            useXmlCoords = 1;

            EV<< "[SimpleNetConfigurator::initializeUnderlay()]\n"
            << "    Using '" << nodeCoordinateSource
            << "' as coordinate source file" << endl;

            maxCoordinate = parseCoordFile(nodeCoordinateSource);
        } else {
            throw cRuntimeError("Coordinate source file not found!");
        }
        check_for_xml_file.close();
    } else {
        useXmlCoords = 0;
        dimensions = 2; //TODO do we need this variable?
        NodeRecord::setDim(dimensions);
        EV << "[SimpleNetConfigurator::initializeUnderlay()]\n"
        << "    Using conventional (random) coordinates for placing nodes!\n"
        << "    (no XML coordinate source file was specified)" << endl;
    }

    // FIXME get address from parameter
    nextFreeAddress = 0x1000001;

    // count the overlay clients
    overlayTerminalCount = 0;

    numCreated = 0;
    numKilled = 0;
}

void SimpleUnderlayConfigurator::migrateNode ( NodeType  type,
TransportAddress addr = NULL 
) [virtual]

Migrates overlay nodes from one access net to another.

Parameters:
type NodeType of the node to migrate
addr NULL for random node

Implements UnderlayConfigurator.

Definition at line 379 of file SimpleUnderlayConfigurator.cc.

{
    Enter_Method_Silent();

    SimpleNodeEntry* entry = NULL;

    if (addr != NULL) {
        SimpleInfo* info =
              dynamic_cast<SimpleInfo*> (globalNodeList->getPeerInfo(*addr));
        if (info != NULL) {
            entry = info->getEntry();
        } else {
            opp_error("SimpleNetConfigurator: Trying to migrate node with "
                      "nonexistant TransportAddress!");
        }
    } else {
        SimpleInfo* info = dynamic_cast<SimpleInfo*> (
                globalNodeList-> getRandomPeerInfo(type.typeID));
        entry = info->getEntry();
    }

    cGate* gate = entry->getUdpIPv4Gate();
    cModule* node = gate->getOwnerModule()->getParentModule();

    // do not migrate node that is already scheduled
    if (scheduledID.count(node->getId()))
        return;

    //std::cout << "migration @ " << tmp_ip << " --> " << address << std::endl;

    // FIXME use only IPv4?
    IPvXAddress address = IPAddress(nextFreeAddress++);

    IPvXAddress tmp_ip = IPAddressResolver().addressOf(node);
    SimpleNodeEntry* newentry;

    int chanIndex = intuniform(0, type.channelTypesRx.size() - 1);
    cChannelType* rxChan = cChannelType::find(type.channelTypesRx[chanIndex].c_str());
    cChannelType* txChan = cChannelType::find(type.channelTypesTx[chanIndex].c_str());

    if (!txChan || !rxChan)
         opp_error("Could not find Channel Type. Most likely parameter "
            "channelTypesRx or channelTypes does not match the channels defined in "
             "channels.ned");

    if (useXmlCoords) {
       newentry = new SimpleNodeEntry(node,
                                      rxChan,
                                      txChan,
                                      sendQueueLength,
                                      entry->getNodeRecord(), entry->getRecordIndex());
        //newentry->getNodeRecord()->ip = address;
    } else {
        newentry = new SimpleNodeEntry(node, rxChan, txChan, fieldSize, sendQueueLength);
    }

    node->bubble("I am migrating!");

    //remove node from bootstrap oracle
    globalNodeList->killPeer(tmp_ip);

    SimpleUDP* simple = check_and_cast<SimpleUDP*> (gate->getOwnerModule());
    simple->setNodeEntry(newentry);

    InterfaceEntry* ie = IPAddressResolver().interfaceTableOf(node)->
                                      getInterfaceByName("dummy interface");
    delete ie->ipv4Data();

    // Add pseudo-Interface to node's interfaceTable
    IPv4InterfaceData* ifdata = new IPv4InterfaceData;
    ifdata->setIPAddress(address.get4());
    ifdata->setNetmask(IPAddress("255.255.255.255"));
    ie->setIPv4Data(ifdata);

    // create meta information
    SimpleInfo* newinfo = new SimpleInfo(type.typeID, node->getId(),
                                         type.context);
    newinfo->setEntry(newentry);

    //add node to bootstrap oracle
    globalNodeList->addPeer(address, newinfo);

    // inform the notification board about the migration
    NotificationBoard* nb = check_and_cast<NotificationBoard*> (
                                      node->getSubmodule("notificationBoard"));
    nb->fireChangeNotification(NF_OVERLAY_TRANSPORTADDRESS_CHANGED);
}

uint32_t SimpleUnderlayConfigurator::parseCoordFile ( const char *  nodeCoordinateSource  )  [protected]

Definition at line 254 of file SimpleUnderlayConfigurator.cc.

Referenced by initializeUnderlay().

{
    cXMLElement* rootElement = ev.getXMLDocument(nodeCoordinateSource);

    // get number of dimensions from attribute of xml rootelement
    dimensions = atoi(rootElement->getAttribute("dimensions"));
    NodeRecord::setDim(dimensions);
    EV << "[SimpleNetConfigurator::parseCoordFile()]\n"
       << "    using " << dimensions << " dimensions: ";

    double max_coord = 0;

    for (cXMLElement *tmpElement = rootElement->getFirstChild(); tmpElement;
         tmpElement = tmpElement->getNextSibling()) {

        // get "ip" and "isRoot" from Attributes (not needed yet)
      /*
       const char* str_ip = tmpElement->getAttribute("ip");
       int tmpIP = 0;
       if (str_ip) sscanf(str_ip, "%x", &tmpIP);
       bool tmpIsRoot = atoi(tmpElement->getAttribute("isroot"));
       */

        // create tmpNode to be added to vector
        NodeRecord* tmpNode = new NodeRecord;

        // get coords from childEntries and fill tmpNodes Array
        int i = 0;
        for (cXMLElement *coord = tmpElement->getFirstChild(); coord;
             coord = coord->getNextSibling()) {

            tmpNode->coords[i] = atof(coord->getNodeValue());

            double newMax = fabs(tmpNode->coords[i]);
            if (newMax > max_coord) {
               max_coord = newMax;
            }
            i++;
        }

        // add to vector
        nodeRecordPool.push_back(make_pair(tmpNode, true));

        //if (nodeRecordPool.size() >= maxSize) break; //TODO use other xml lib
    }

    EV << nodeRecordPool.size()
       << " nodes added to vector \"nodeRecordPool\"." << endl;

#if OMNETPP_VERSION>=0x0401
    // free memory used for xml document
    ev.forgetXMLDocument(nodeCoordinateSource);
    malloc_trim(0);
#endif
    
    return (uint32_t)ceil(max_coord);
}

void SimpleUnderlayConfigurator::preKillNode ( NodeType  type,
TransportAddress addr = NULL 
) [virtual]

Notifies and schedules overlay nodes for removal.

Parameters:
type NodeType of the node to remove
addr NULL for random node

Implements UnderlayConfigurator.

Definition at line 312 of file SimpleUnderlayConfigurator.cc.

{
    Enter_Method_Silent();

    SimpleNodeEntry* entry = NULL;
    SimpleInfo* info;

    if (addr == NULL) {
        addr = globalNodeList->getRandomAliveNode(type.typeID);

        if (addr == NULL) {
            // all nodes are already prekilled
            std::cout << "all nodes are already prekilled" << std::endl;
            return;
        }
    }

    info = dynamic_cast<SimpleInfo*> (globalNodeList->getPeerInfo(*addr));

    if (info != NULL) {
        entry = info->getEntry();
        globalNodeList->setPreKilled(*addr);
    } else {
        opp_error("SimpleNetConfigurator: Trying to pre kill node "
                  "with nonexistant TransportAddress!");
    }

    uint32_t effectiveType = info->getTypeID();
    cGate* gate = entry->getUdpIPv4Gate();

    cModule* node = gate->getOwnerModule()->getParentModule();

    if (scheduledID.count(node->getId())) {
        std::cout << "SchedID" << std::endl;
        return;
    }

    // remove node from bootstrap oracle
    globalNodeList->removePeer(IPAddressResolver().addressOf(node));

    // put node into the kill list and schedule a message for final removal
    // of the node
    killList.push_front(IPAddressResolver().addressOf(node));
    scheduledID.insert(node->getId());

    overlayTerminalCount--;
    numKilled++;

    churnGenerator[effectiveType]->terminalCount--;

    // update display
    setDisplayString();

    // inform the notification board about the removal
    NotificationBoard* nb = check_and_cast<NotificationBoard*> (
                             node-> getSubmodule("notificationBoard"));
    nb->fireChangeNotification(NF_OVERLAY_NODE_LEAVE);

    double random = uniform(0, 1);
    if (random < gracefulLeaveProbability) {
        nb->fireChangeNotification(NF_OVERLAY_NODE_GRACEFUL_LEAVE);
    }

    cMessage* msg = new cMessage();
    scheduleAt(simTime() + gracefulLeaveDelay, msg);
}

void SimpleUnderlayConfigurator::setDisplayString (  )  [protected, virtual]

Prints statistics.

Implements UnderlayConfigurator.

Definition at line 507 of file SimpleUnderlayConfigurator.cc.

Referenced by createNode(), and preKillNode().

{
    // Updates the statistics display string.
    char buf[80];
    sprintf(buf, "%i overlay terminals", overlayTerminalCount);
    getDisplayString().setTagArg("t", 0, buf);
}


Member Data Documentation

std::deque<IPvXAddress> SimpleUnderlayConfigurator::killList [protected]

stores nodes scheduled to be killed

Definition at line 100 of file SimpleUnderlayConfigurator.h.

Referenced by handleTimerEvent(), and preKillNode().

Definition at line 111 of file SimpleUnderlayConfigurator.h.

Referenced by initializeUnderlay().

adress of the node that will be created next

Definition at line 99 of file SimpleUnderlayConfigurator.h.

Referenced by createNode(), initializeUnderlay(), and migrateNode().

Definition at line 110 of file SimpleUnderlayConfigurator.h.

Referenced by createNode(), and initializeUnderlay().

number of overall created overlay terminals

Definition at line 116 of file SimpleUnderlayConfigurator.h.

Referenced by createNode(), finishUnderlay(), and initializeUnderlay().

number of overall killed overlay terminals

Definition at line 117 of file SimpleUnderlayConfigurator.h.

Referenced by finishUnderlay(), initializeUnderlay(), and preKillNode().

std::set<int> SimpleUnderlayConfigurator::scheduledID [protected]

stores nodeIds to prevent migration of prekilled nodes

Definition at line 101 of file SimpleUnderlayConfigurator.h.

Referenced by handleTimerEvent(), migrateNode(), and preKillNode().

send queue length of overlay terminals

Definition at line 103 of file SimpleUnderlayConfigurator.h.

Referenced by createNode(), getSendQueueLenghth(), initializeUnderlay(), and migrateNode().

Definition at line 107 of file SimpleUnderlayConfigurator.h.

Referenced by createNode(), and initializeUnderlay().


The documentation for this class was generated from the following files: