Files
scandocs/uni/masterarbeit/source/moversight/app/MaintanceApplication.cc
2014-06-30 13:58:10 +02:00

595 lines
15 KiB
C++

/*
* File: MaintanceApplication.cc
* Author: stubbfel
*
* Created on June 29, 2013
*/
#include "MaintanceApplication.h"
#include "Dispatcher.h"
#include "Moversight.h"
#include "ms/Invitation.h"
#include "common/transport/TransportAddress.h"
#include "simutils/OmnetppIniUtils.h"
#include "mt/msg/GroupData.h"
#include <fstream>
#include "ms/events/GroupClosedEvent.h"
#include "ms/events/JoinRequestEvent.h"
#include "ms/events/LocalPeerUpdatedEvent.h"
#include "ms/events/PeerJoinedEvent.h"
#include "ms/events/PeerLeftEvent.h"
#include "mt/events/MulticastMessageDroppedEvent.h"
#undef DEBUG
#define DEBUG(msg) if (module.isPrintDebugAPP()) \
MOV_DEBUG << "APP@"<<(dis->getLocalState()==DISJOINED?"TA_":"");\
if(dis->getLocalState()==DISJOINED){MOV_DEBUG << module.getLocalAddress();}\
else{MOV_DEBUG<< dis->getMembershipService().getLocalID();}MOV_DEBUG<<" "<<msg<<std::endl;
namespace ubeeme {
namespace moversight {
const unsigned int MaintanceApplication::INITIAL_FAKEID;
const unsigned int MaintanceApplication::MS_TO_INT_FACTOR;
/**
* @brief Constructor
* @param m A reference to the moversight instance
*/
MaintanceApplication::MaintanceApplication(Moversight & m) : Application(m, "MaintanceApplication"), RTTStat(m, "RTT") { /*, groupSizeStat(m, "groupSize"), groupSize(0) */
inGroup = false;
stopTest = false;
emptyCommandList = false;
nextCommand = true;
}
/**
* @brief Destructor
*/
MaintanceApplication::~MaintanceApplication() {
}
void
MaintanceApplication::initialise() {
dis->subscribe<GroupClosedEvent>(this);
dis->subscribe<PeerJoinedEvent>(this);
dis->subscribe<PeerLeftEvent>(this);
dis->subscribe<LocalPeerUpdatedEvent>(this);
dis->subscribe<JoinRequestEvent>(this);
dis->subscribe<MulticastMessageDroppedEvent>(this);
}
void
MaintanceApplication::finalise() {
dis->unsubscribeAll(this);
}
/**
* @brief Starts the given test case.
* @param i The number of the test case to start.
*/
void
MaintanceApplication::startTestCase(unsigned int i) {
if (stopTest) {
return;
}
switch (i) {
case 0:
testCase00();
break;
case 1:
testCase01();
break;
case 2:
testCase02();
break;
case 3:
testCase03();
break;
case 4:
testCase04();
break;
case 5:
testCase05();
break;
case 6:
testCase06();
break;
default:
throw NotImplementedYetException("not implemented");
break;
}
}//End startTestCase
/**
*@brief simple test run with random leaves and joins
*/
void
MaintanceApplication::testCase00() {
joinRate = 1;
leaveRate = 1;
defaultBehav();
}//End testCase00
/**
*@brief simple test run coordinatet leaves and joins
*/
void
MaintanceApplication::testCase01() {
joinRate = 1; // == 100%
leaveRate = 2; // == 50%
commandsFileName = "commands/comt01.txt";
coordinateBehav();
module.scheduleTestCase(1);
}//End testCase01
/**
*@brief testrun for simultaneously invataitons
*/
void
MaintanceApplication::testCase02() {
joinRate = 1; // == 100%
leaveRate = 1; // == 0%
defaultBehav2();
}//End testCase02
/**
*@brief coordiante testrun, if all commands are executed then moduel==1 start to send groupdatas
*/
void
MaintanceApplication::testCase03() {
commandsFileName = "commands/com.txt";
coordinateBehav();
if (moduleIndex == 1 && dis->getLocalState() == JOINED) {
// abuse sendMessage for transmitting first sending time of the messages
sendKickMessage(createFakeID(GenericTime::currentTime().dbl() * MS_TO_INT_FACTOR));
}//End if
module.scheduleTestCase(1);
}
/**
*@brief test run, for testing random forces role switch (module== ire sending RSA Messages)
*/
void
MaintanceApplication::testCase04() {
commandsFileName = "commands/comt04.txt";
module.scheduleTestCase(45);
coordinateBehav();
if (dis->getLocalState() == JOINED &&
commands.size() < 1 &&
moduleIndex == 1 &&
dis->getLocalSubState() != FLUSHING) {
PeerIDList masterIdList = dis->getMembershipService().getMasterPeerIDList();
PeerID switchMasterId = masterIdList.get(rand() % masterIdList.size());
dis->getMaintenanceRoleService().sendRSAMessage(switchMasterId);
}
module.scheduleTestCase(1);
}
/**
*@brief uncoordiante testrun, moduel==1 send groupdatas
*/
void
MaintanceApplication::testCase05() {
joinRate = 5;
leaveRate = 100;
defaultBehav();
if (moduleIndex == 1 && dis->getLocalState() == JOINED) {
// abuse sendMessage for sending "useless" messages
sendKickMessage(createFakeID(0));
}//End if
module.scheduleTestCase(1);
}
/**
*@brief coordiante testrun, if all commands are executed then moduel==1 start to send groupdatas (like testcase 3 but sending messages as a burst)
*/
void
MaintanceApplication::testCase06() {
commandsFileName = "commands/comt03.txt";
//module.scheduleTestCase(45);
coordinateBehav();
if (moduleIndex == 1 && dis->getLocalState() == JOINED && emptyCommandList) {
// send a the current time as fakeID
sendKickMessage(createFakeID(GenericTime::currentTime().dbl() * MS_TO_INT_FACTOR));
module.scheduleTestCase(0.001);
} else {
module.scheduleTestCase(1);
}
}
/**
* @brief excute the normal behaviour of the app, depends of the join- and
* leaverate, the module==1 will be insert peers. every Peer decided self,
* when they want to leave the group (Except module==1||2 )
*/
void
MaintanceApplication::defaultBehav() {
moduleIndex = module.getLocalAddress().getHostAddress().get4().getDByte(3);
if (initApp) {
candidates = OmnetppIniUtils::getDestinationAddressesFromOmnetppIni(module);
initApp = false;
}//End if
//------------------------------------------------------------------
//run the app
//------------------------------------------------------------------
if (moduleIndex == 1) { // starts counting at 1
//we have more candidates?
if (candidates.size() > 0) {
int join = rand() % joinRate;
if (join == 0) {
TransportAddress first = candidates.first();
candidates.remove(first);
invitePeer(first);
}
}
//module.scheduleTestCase(45);
} else {
if (dis->getLocalState() == JOINED) {
inGroup = true;
} else {
inGroup = false;
}
if (inGroup && dis->getGroupSize() > 2) {
int leave = rand() % leaveRate;
if (leave == 1) {
leaveGroup();
}
//module.scheduleTestCase(45);
}
}//End if
module.scheduleTestCase(45);
}
/**
* @brief excute the normal behaviour of the app, depends of the join- and
* leaverate, the module==1||2 will be insert peers. every Peer decided self,
* when they want to leave the group (Except module==1||2 )
*/
void
MaintanceApplication::defaultBehav2() {
moduleIndex = module.getLocalAddress().getHostAddress().get4().getDByte(3);
if (initApp) {
candidates = OmnetppIniUtils::getDestinationAddressesFromOmnetppIni(module);
initApp = false;
}//End if
//------------------------------------------------------------------
//run the app
//------------------------------------------------------------------
if (moduleIndex == 1) { // starts counting at 1
//we have more candidates?
if (candidates.size() > 0) {
int join = rand() % joinRate;
if (join == 0) {
TransportAddress first = candidates.first();
candidates.remove(first);
invitePeer(first);
}
}
//module.scheduleTestCase(45);
} else if (moduleIndex == 2) { // starts counting at 2
if (dis->getLocalState() == JOINED) {
inGroup = true;
} else {
inGroup = false;
}
//we have more candidates?
if (candidates.size() > 0 && inGroup) {
int join = rand() % joinRate;
if (join == 0) {
TransportAddress last = candidates.get(candidates.size() - 1);
candidates.remove(last);
invitePeer(last);
}
}
//module.scheduleTestCase(45);
} else {
if (dis->getLocalState() == JOINED) {
inGroup = true;
} else {
inGroup = false;
}
if (inGroup && dis->getGroupSize() > 2) {
int leave = rand() % leaveRate;
if (leave == 1) {
leaveGroup();
}
//module.scheduleTestCase(45);
}
}//End if
module.scheduleTestCase(45);
}
/**
* @brief excute the coordinated behaviour of the app, depends of the join- and
* leavecommands from a certean, the module==1 will be insert or remove peers
*/
void
MaintanceApplication::coordinateBehav() {
moduleIndex = module.getLocalAddress().getHostAddress().get4().getDByte(3);
if (initApp) {
candidates = OmnetppIniUtils::getDestinationAddressesFromOmnetppIni(module);
initApp = false;
if (moduleIndex == 1) {
std::ifstream commandFile(commandsFileName.c_str());
if (commandFile.is_open()) {
std::string command;
DEBUG("Load commands");
while (commandFile.good()) {
std::getline(commandFile, command);
DEBUG(command);
commands.add(command);
}
commandFile.close();
}
module.scheduleTestCase(45);
}//End if
}//End if
//------------------------------------------------------------------
//run the app
//------------------------------------------------------------------
if (moduleIndex == 1) { // starts counting at 1
//we have more candidates?
if (commands.size() > 0 && nextCommand == true) {
std::string command = commands.first();
commands.pop();
DEBUG("exec command " << command);
switch (command[0]) {
case 'J':
nextCommand = false;
if (candidates.size() > 0) {
TransportAddress firstAddr = candidates.first();
invitePeer(firstAddr);
candidates.pop();
}
break;
case 'L': {
nextCommand = false;
PeerID kickPeerID;
if (command.size() == 3) {
size_t firstNumber = (size_t)(command[1] - '0');
size_t secondNumber = (size_t)(command[2] - '0');
kickPeerID = firstNumber * 10 + secondNumber;
} else {
kickPeerID = (PeerID)(command[1] - '0');
}
sendKickMessage(kickPeerID);
}
break;
default:
break;
}
} else if (commands.size() == 0) {
emptyCommandList = true;
}
// module.scheduleTestCase(45);
}
}
void
MaintanceApplication::sendKickMessage(PeerID pId) {
DEBUG("sendData - stream dummy data to the group");
GroupData data;
data.setData(peerIDToByte(pId));
dis->sendMessage(data);
}
/**
* @brief convert a PeerID to a ByteArray
* @param id which has to been convert
*/
ByteArray
MaintanceApplication::peerIDToByte(PeerID pId) {
ByteArray array;
array.push_back(pId.getValue() & 0xff);
array.push_back(pId.getValue() >> 8 & 0xff);
array.push_back(pId.getValue() >> 16 & 0xff);
array.push_back(pId.getValue() >> 24 & 0xff);
return array;
}
/**
* @brief convert a ByteArray to a PeerId
* @param array which has to been convert
*/
PeerID
MaintanceApplication::byteToPeerID(ByteArray array) {
unsigned int intPid = 0;
char* chPID = (char*) &intPid;
*chPID = array[0];
chPID++;
*chPID = array[1];
chPID++;
*chPID = array[2];
chPID++;
*chPID = array[3];
return PeerID(intPid);
}
/**
* @brief Invites a peer to a the moversight group.
* @param ta The transport address of the peer to invite.
*/
void
MaintanceApplication::invitePeer(TransportAddress & ta) {
PeerDescription pDesc;
dis->invitePeer(ta, pDesc);
}
/**
* @brief Leaves the current group. The peer leafs the current group be
* emmiting a LeaveAnnounce within the current group.
*/
void
MaintanceApplication::leaveGroup() {
dis->leaveGroup();
}
/**
* @brief Handle an incoming JoinRequestEvent.
* @param e The event.
*/
void
MaintanceApplication::handleEvent(const JoinRequestEvent & e) {
PeerDescription desc;
PeerResources resource;
dis->acceptInvitation(e.getInvitation(), "accept invitation", desc, module.getPeerResources());
}
/**
* @brief Handle PeerJoinedEvent.
* @param e The event.
*/
void
MaintanceApplication::handleEvent(const PeerJoinedEvent & e) {
nextCommand = true;
}
/**
* @brief Handle an incoming PeerLeftEvent.
* @param e The event.
*/
void
MaintanceApplication::handleEvent(const PeerLeftEvent & e) {
if (moduleIndex == 1) {
if (!candidates.contains(e.getPeer().getLocalAddress())) {
candidates.add(e.getPeer().getLocalAddress());
}
}
nextCommand = true;
}
/**
* @brief Handle an incoming LocalPeerUpdatedEvent.
* @param e The event.
*/
void
MaintanceApplication::handleEvent(const LocalPeerUpdatedEvent & e) {
std::stringstream buf;
buf << "Peer-State - PID: " << e.getPeer().getPeerState();
DEBUG(buf.str().c_str());
}
/**
* @brief Handle an incoming GroupClosedEvent.
* @param e The event.
*/
void
MaintanceApplication::handleEvent(const GroupClosedEvent & e) {
if (moduleIndex == 1) {
stopTest = true;
}
}
/**
* @brief handler for incomming Group Data
* @param data, referennce of the new messages
* @param sender , id of the peer which sended this message
*/
void
MaintanceApplication::receiveGroupData(const GroupData & dat, const PeerID sender) {
ByteArray array = dat.getData();
PeerID pID = byteToPeerID(array);
std::stringstream buf;
buf << "receiveStreamMessage - kick Peer" << pID;
//std::cerr << "buf " << buf << "\n";
DEBUG(buf.str().c_str());
if (pID == dis->getLocalPeer().getPeerID()) {
leaveGroup();
}//End if
else if (pID > INITIAL_FAKEID) {
// is a fade id;
meassuringRTT(pID, dat);
}//end else if
}
/**
* @brief method extract from a abuse peerId the sending item and calculate the rtt of a messages
* @param peerId, is a faked id. its the sendingtime + 1000
* @param dat, referennce of the message
*/
void
MaintanceApplication::meassuringRTT(PeerID peerId, const GroupData & dat) {
int sendTime = peerId.getValue() - INITIAL_FAKEID;
int reciveTime = GenericTime::currentTime().dbl() * MS_TO_INT_FACTOR;
int rtt = reciveTime - sendTime;
RTTStat.record(rtt);
MessageReference msgref = dat.getMessageReference();
DEBUG("rtt of msg " << msgref << " = " << rtt << "ms");
}
/**
* @brief methed create a fakepid
* @param value, parameter wich has to bo corvert to peerID
*/
PeerID
MaintanceApplication::createFakeID(unsigned int value) {
return PeerID(INITIAL_FAKEID + value);
}
/**
* @brief Handle an incoming MulticastMessageDroppedEvent.
* @param e The event.
*/
void MaintanceApplication::handleEvent(const MulticastMessageDroppedEvent& e) {
const MulticastMessage & msg = e.getMessage();
DEBUG("message " << msg << "(MREF=" << msg.getMessageReference() << ") is dropped !!!");
}
}
}