Classes | Public Member Functions | Protected Types | Protected Member Functions | Protected Attributes

CBRDHT Class Reference

A Distributed Hash Table (DHT) for KBR protocols. More...

#include <CBR-DHT.h>

Inheritance diagram for CBRDHT:
BaseApp BaseRpc BaseTcpSupport RpcListener

List of all members.

Classes

struct  GetMapEntry
struct  PutMapEntry

Public Member Functions

 CBRDHT ()
virtual ~CBRDHT ()

Protected Types

typedef std::vector< NodeHandleReplicaVector

Protected Member Functions

void initializeApp (int stage)
 initializes derived class-attributes
void finishApp ()
 collects statistical data of derived app
void handleTimerEvent (cMessage *msg)
bool handleRpcCall (BaseCallMessage *msg)
void handleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt)
void handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, cPolymorphic *context, int rpcId, const OverlayKey &destKey)
void handleUpperMessage (cMessage *msg)
 handleUpperMessage gets called of handleMessage(cMessage* msg) if msg arrivedOn from_upperTier (currently msg gets deleted in this function)
void handlePutRequest (DHTPutCall *dhtMsg)
void handleGetRequest (CBRDHTGetCall *dhtMsg)
void handlePutResponse (DHTPutResponse *dhtMsg, int rpcId)
void handleGetResponse (CBRDHTGetResponse *dhtMsg, int rpcId)
void handlePutCAPIRequest (DHTputCAPICall *capiPutMsg)
void handleGetCAPIRequest (DHTgetCAPICall *capiGetMsg, int teamnum=0)
void handleDumpDhtRequest (DHTdumpCall *call)
void update (const NodeHandle &node, bool joined)
 Common API function: informs application about neighbors and own nodeID.
void handleLookupResponse (LookupResponse *lookupMsg)
int resultValuesBitLength (DHTGetResponse *msg)

Protected Attributes

int numReplica
uint8_t numReplicaTeams
double maintenanceMessages
double normalMessages
double numBytesMaintenance
double numBytesNormal
double lastGetCall
std::map< unsigned int,
BaseCallMessage * > 
rpcIdMap
 List of the Rpc Ids of the messages sent following the reception of an rpc request (the second member).
std::map< int, GetMapEntrygetMap
std::map< int, PutMapEntryputMap
DHTDataStoragedataStorage
 pointer to the dht data storage
CoordBasedRoutingcoordBasedRouting
NeighborCacheneighborCache

Detailed Description

A Distributed Hash Table (DHT) for KBR protocols.

A Distributed Hash Table (DHT) for KBR protocols

Definition at line 48 of file CBR-DHT.h.


Member Typedef Documentation

typedef std::vector<NodeHandle> CBRDHT::ReplicaVector [protected]

Definition at line 55 of file CBR-DHT.h.


Constructor & Destructor Documentation

CBRDHT::CBRDHT (  ) 

Definition at line 38 of file CBR-DHT.cc.

{
    dataStorage = NULL;
}

CBRDHT::~CBRDHT (  )  [virtual]

Definition at line 43 of file CBR-DHT.cc.

{
    std::map<unsigned int, BaseCallMessage*>::iterator it;

    for (it = rpcIdMap.begin(); it != rpcIdMap.end(); it++) {
        delete it->second;
        it->second = NULL;
    }

    std::map<int, GetMapEntry>::iterator it2;
    for (it2 = getMap.begin(); it2 != getMap.end(); it2++) {
        //cancelAndDelete(it2->second.callMsg);
        delete it2->second.callMsg;
        it2->second.callMsg = NULL;
    }

    std::map<int, PutMapEntry>::iterator it3;

    for (it3 = putMap.begin(); it3 != putMap.end(); it3++) {
        //if (it3->second.callMsg != NULL) {
        //    cancelAndDelete(it3->second.callMsg);
        //}
        delete it3->second.callMsg;
        it3->second.callMsg = NULL;
    }

    rpcIdMap.clear();
    getMap.clear();
    putMap.clear();

    if (dataStorage != NULL) {
        dataStorage->clear();
    }
}


Member Function Documentation

void CBRDHT::finishApp (  )  [protected, virtual]

collects statistical data of derived app

Reimplemented from BaseApp.

Definition at line 911 of file CBR-DHT.cc.

{
    simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);

    if (time != 0) {
        // std::cout << dataStorage->getSize() << " " << overlay->getThisNode().getKey().toString(16) << std::endl;
        globalStatistics->addStdDev("DHT: Sent Maintenance Messages/s",
                                    maintenanceMessages / time);
        globalStatistics->addStdDev("DHT: Sent Normal Messages/s",
                                    normalMessages / time);
        globalStatistics->addStdDev("DHT: Sent Maintenance Bytes/s",
                                    numBytesMaintenance / time);
        globalStatistics->addStdDev("DHT: Sent Normal Bytes/s",
                                    numBytesNormal / time);
    }
}

void CBRDHT::handleDumpDhtRequest ( DHTdumpCall call  )  [protected]

Definition at line 547 of file CBR-DHT.cc.

Referenced by handleRpcCall().

{
    DHTdumpResponse* response = new DHTdumpResponse();
    DhtDumpVector* dumpVector = dataStorage->dumpDht();

    response->setRecordArraySize(dumpVector->size());

    for (uint i = 0; i < dumpVector->size(); i++) {
        response->setRecord(i, (*dumpVector)[i]);
    }

    delete dumpVector;

    sendRpcResponse(call, response);
}

void CBRDHT::handleGetCAPIRequest ( DHTgetCAPICall capiGetMsg,
int  teamnum = 0 
) [protected]

Definition at line 417 of file CBR-DHT.cc.

Referenced by handleGetResponse(), handleRpcCall(), and handleRpcTimeout().

                                                                         {
    // Extended multi team version, default: teamnum = 0
        if (teamnum >= numReplicaTeams)
                return;

        OverlayKey originalKey = capiGetMsg->getKey();
        std::vector<OverlayKey> possibleKeys;

        assert(!originalKey.isUnspecified());
        possibleKeys.push_back(originalKey);

        for (int i = 1; i < numReplicaTeams; i++) {
                // multiple SHA1 hashing of original key
                OverlayKey keyHash = originalKey;
                for (int j = 0; j < i; j++) {
                        keyHash = OverlayKey::sha1(BinaryValue(keyHash.toString(16).c_str()));
                }
                assert(!keyHash.isUnspecified());
                possibleKeys.push_back(keyHash);
        }

    // Order possible keys by euclidian distance to this node
    std::vector<OverlayKey> orderedKeys;
    OverlayKey compareKey = overlay->getThisNode().getKey();

    while (possibleKeys.size() > 0) {
        OverlayKey bestKey = possibleKeys[0];
        int bestpos = 0;

        // TODO: i = 1?
        for (uint i = 0; i < possibleKeys.size(); i++) {
            //std::cout << neighborCache->getOwnEuclidianDistanceToKey(possibleKeys[i]) << std::endl;
            if (coordBasedRouting
                    ->getEuclidianDistanceByKeyAndCoords(possibleKeys[i],
                                                         ((const Nps&)neighborCache->getNcsAccess()).getOwnCoordinates(), //TODO
                                                         overlay->getBitsPerDigit()) <
                coordBasedRouting
                    ->getEuclidianDistanceByKeyAndCoords(bestKey,
                                                         ((const Nps&)neighborCache->getNcsAccess()).getOwnCoordinates(), //TODO
                                                         overlay->getBitsPerDigit())) {
                bestKey = possibleKeys[i];
                bestpos = i;
            }
        }
        //std::cout << neighborCache->getOwnEuclidianDistanceToKey(bestKey) << "\n" << std::endl;
        orderedKeys.push_back(bestKey);
        possibleKeys.erase(possibleKeys.begin()+bestpos);
    }

    /*
    std::cout << "NodeID: " << overlay->getThisNode().getKey().toString(16) << std::endl;
    std::cout << "Original Key: " << originalKey.toString(16) << std::endl;
    for (int i = 0; i < orderedKeys.size(); i++) {
        std::cout << "Sorted Key " << i << ": " << orderedKeys[i].toString(16) << " (" << overlay->getOwnEuclidianDistanceToKey(orderedKeys[i]) << ")" << std::endl;
    }
    */

    OverlayKey searchKey = orderedKeys[teamnum];

#define DIRECT_ROUTE_GET
#ifndef DIRECT_ROUTE_GET

    LookupCall* replicaMsg = new LookupCall();
    replicaMsg->setKey(searchKey);
    replicaMsg->setNumSiblings(floor(numReplica / numReplicaTeams));
    int nonce = sendInternalRpcCall(OVERLAY_COMP, replicaMsg);
    rpcIdMap.insert(make_pair(nonce, capiGetMsg));
    lastGetCall = SIMTIME_DBL(simTime());

#else

    GetMapEntry mapEntry;
    mapEntry.numSent = 0;

    // Multi team version: Already mapEntry from earlier team?
    std::map<int, GetMapEntry>::iterator it2 =
        getMap.find(capiGetMsg->getNonce());

    if (it2 != getMap.end()) {
        mapEntry = it2->second;
    } else {
        mapEntry.teamNumber = 0;
    }
    mapEntry.numAvailableReplica = 1;//lookupMsg->getSiblingsArraySize();
    mapEntry.numResponses = 0;
    mapEntry.callMsg = capiGetMsg;
    mapEntry.hashVector = NULL;
    mapEntry.replica.clear();
    for (unsigned int i = 0; i < 1/*lookupMsg->getSiblingsArraySize()*/; i++) {
        // Simplified GET Request: Just one real request, rest is for fallback
        if (i == 0) {
            CBRDHTGetCall* dhtMsg = new CBRDHTGetCall();

            dhtMsg->setOriginalKey(capiGetMsg->getKey());
            dhtMsg->setKey(searchKey);//lookupMsg->getKey());

            dhtMsg->setIsHash(false);
            dhtMsg->setKind(capiGetMsg->getKind());
            dhtMsg->setId(capiGetMsg->getId());
            dhtMsg->setBitLength(GETCALL_L(dhtMsg));
            RECORD_STATS(normalMessages++;
            numBytesNormal += dhtMsg->getByteLength());

            /*int nonce = */sendRouteRpcCall(TIER1_COMP, searchKey, dhtMsg,
                                         NULL, DEFAULT_ROUTING, -1, 0,
                                         capiGetMsg->getNonce());

            //rpcIdMap.insert(make_pair(nonce, capiGetMsg));
            //sendRouteRpcCall(TIER1_COMP, lookupMsg->getSiblings(i), dhtMsg,
            //                 NULL, DEFAULT_ROUTING, -1, 0,
            //                 capiGetMsg->getNonce());
            mapEntry.numSent++;
        } else {
            //We don't send, we just store the remaining keys as fallback
            //mapEntry.replica.push_back(lookupMsg->getSiblings(i));
        }
    }
    /*
                std::cout << "New replica: " <<  std::endl;
                for (int i = 0; i < mapEntry.replica.size(); i++) {
                    std::cout << mapEntry.replica[i] << std::endl;
                }
                std::cout << "*************************" << std::endl;
     */
    if (it2 != getMap.end())
        getMap.erase(it2);
    getMap.insert(make_pair(capiGetMsg->getNonce(), mapEntry));
#endif
}

void CBRDHT::handleGetRequest ( CBRDHTGetCall dhtMsg  )  [protected]

Definition at line 331 of file CBR-DHT.cc.

Referenced by handleRpcCall().

{
    std::string tempString = "GET_REQUEST received: "
            + std::string(dhtMsg->getKey().toString(16));

    getParentModule()->getParentModule()->bubble(tempString.c_str());

    BinaryValue storedValue;
    DhtDataEntry* dataEntry = dataStorage->getDataEntry(dhtMsg->getKey(), 1, 1);
    if (dataEntry) {
        storedValue = dataStorage->getDataEntry(dhtMsg->getKey(), 1, 1)->value;
    } else {
        storedValue = BinaryValue::UNSPECIFIED_VALUE;
    }

    // send back
    CBRDHTGetResponse* responseMsg = new CBRDHTGetResponse();

    responseMsg->setKey(dhtMsg->getKey());
    responseMsg->setOriginalKey(dhtMsg->getOriginalKey());
    responseMsg->setIsHash(false);
    if (storedValue.isUnspecified()) {
        //responseMsg->setValue(BinaryValue::UNSPECIFIED_VALUE);
        DhtDumpEntry result;
        result.setKey(dhtMsg->getKey());
        result.setValue(BinaryValue::UNSPECIFIED_VALUE);
        responseMsg->setResultArraySize(1);
        responseMsg->setResult(0, result);
    } else {
        //responseMsg->setValue(storedValue);
        DhtDumpEntry result;
        result.setKey(dhtMsg->getKey());
        result.setValue(storedValue);
        responseMsg->setResultArraySize(1);
        responseMsg->setResult(0, result);
    }
    rpcIdMap.insert(make_pair(dhtMsg->getNonce(), (BaseCallMessage*)NULL));

    responseMsg->setBitLength(GETRESPONSE_L(responseMsg));
    RECORD_STATS(normalMessages++;
                 numBytesNormal += responseMsg->getByteLength());
    sendRpcResponse(dhtMsg, responseMsg);
}

void CBRDHT::handleGetResponse ( CBRDHTGetResponse dhtMsg,
int  rpcId 
) [protected]

Definition at line 586 of file CBR-DHT.cc.

Referenced by handleRpcResponse().

{
        std::map<unsigned int, BaseCallMessage*>::iterator it =
            rpcIdMap.find(dhtMsg->getNonce());
    std::map<int, GetMapEntry>::iterator it2 =
            getMap.find(rpcId);

    //unknown request
    if (it2 == getMap.end()) {
        std::cout << "- 1 -" << std::endl;
        return;
    }

    if (!dhtMsg->getIsHash()) {
        //std::cout << "[" << overlay->getThisNode().getIp() << "] " << "Received an answer! Sending up key " << dhtMsg->getKey().toString(16) << "(orig: " << dhtMsg->getOriginalKey().toString(16) << ") -- value " << dhtMsg->getHashValue() << std::endl;
        //std::cout << "Replica left: " << it2->second.replica.size() << std::endl;

        if (dhtMsg->getHashValue().size() > 0 || dhtMsg->getResultArraySize() > 0) {
            // Successful Lookup, received a value
            DHTgetCAPIResponse* capiGetRespMsg = new DHTgetCAPIResponse();
            //capiGetRespMsg->setKey(dhtMsg->getOriginalKey());
            //capiGetRespMsg->setValue(dhtMsg->getHashValue());
            DhtDumpEntry result;
            result.setKey(dhtMsg->getKey());
            result.setValue(dhtMsg->getResult(0).getValue());//getHashValue());
            capiGetRespMsg->setResultArraySize(1);
            capiGetRespMsg->setResult(0, result);

            //std::cout << "[" << overlay->getThisNode().getIp() << "] " << "SUCCESSFUL LOOKUP! Sending up key " << dhtMsg->getKey().toString(16) << "(orig: " << dhtMsg->getOriginalKey().toString(16) << ") -- value " << dhtMsg->getHashValue() << std::endl;

            capiGetRespMsg->setIsSuccess(true);
            sendRpcResponse(it2->second.callMsg, capiGetRespMsg);
            getMap.erase(rpcId);
            return;
        } else if (it2->second.replica.size() > 0) {
            // Received empty value, try fallback replica
            NodeHandle fallbackReplica = it2->second.replica.back();

            std::cout << "[" << overlay->getThisNode().getIp() << "] " << "Empty value received. Asking replica now ("<< it2->second.replica.size()<<" left)!" << std::endl;

            CBRDHTGetCall* dhtRecall = new CBRDHTGetCall();
            dhtRecall->setOriginalKey(dhtMsg->getOriginalKey());
            dhtRecall->setKey(dhtMsg->getKey());
            dhtRecall->setIsHash(false);
            dhtRecall->setBitLength(GETCALL_L(dhtRecall));
            RECORD_STATS(normalMessages++;
            numBytesNormal += dhtRecall->getByteLength());
            sendRouteRpcCall(TIER1_COMP, fallbackReplica, dhtRecall,
                             NULL, DEFAULT_ROUTING, -1, 0,
                             it2->second.callMsg->getNonce());
            it2->second.numSent++;
            it2->second.replica.pop_back();
            return;
        } else if (it2->second.teamNumber < (numReplicaTeams - 1)) {
            // No more fallback replica in this team, try next one

            std::cout << "it2->second.teamNumber (" << it2->second.teamNumber << ") < (numReplicaTeams - 1) (" << (numReplicaTeams - 1) << ")" << std::endl;
            std::cout << "[" << overlay->getThisNode().getIp() << "] " << "No more fallback replica in this team "<< it2->second.teamNumber<<". Trying next one ("<< it2->second.teamNumber+1 <<  ")..." << std::endl;

            it2->second.teamNumber++;
            handleGetCAPIRequest(it2->second.callMsg, it2->second.teamNumber);
            return;
        } else {
            // No more replica, no more teams, send success == false to Tier 2 :(

            std::cout << "[" << overlay->getThisNode().getIp() << "] " << "No more fallback replica. Lookup failed. :(" << std::endl;

            DHTgetCAPIResponse* capiGetRespMsg = new DHTgetCAPIResponse();
            //capiGetRespMsg->setKey(dhtMsg->getOriginalKey());
            //capiGetRespMsg->setValue(BinaryValue::UNSPECIFIED_VALUE);
            DhtDumpEntry result;
            result.setKey(dhtMsg->getKey());
            result.setValue(BinaryValue::UNSPECIFIED_VALUE);
            capiGetRespMsg->setResultArraySize(1);
            capiGetRespMsg->setResult(0, result);
            capiGetRespMsg->setIsSuccess(false);
            sendRpcResponse(it2->second.callMsg, capiGetRespMsg);
            getMap.erase(rpcId);
        }
    }
}

void CBRDHT::handleLookupResponse ( LookupResponse lookupMsg  )  [protected]

Definition at line 737 of file CBR-DHT.cc.

Referenced by handleRpcResponse().

{
        std::map<unsigned int, BaseCallMessage*>::iterator it =
            rpcIdMap.find(lookupMsg->getNonce());

    if (it == rpcIdMap.end() || it->second == NULL)
        return;

    if (dynamic_cast<DHTputCAPICall*> (it->second)) {

        #if 0
        cout << "DHT::handleLookupResponse(): PUT "
             << lookupMsg->getKey() << " ("
             << overlay->getThisNode().getKey() << ")" << endl;

        for (unsigned int i = 0; i < lookupMsg->getSiblingsArraySize(); i++) {
            cout << i << ": " << lookupMsg->getSiblings(i) << endl;
        }
#endif

        DHTputCAPICall* capiPutMsg = dynamic_cast<DHTputCAPICall*> (it->second);
        rpcIdMap.erase(lookupMsg->getNonce());


        if ((lookupMsg->getIsValid() == false)
                || (lookupMsg->getSiblingsArraySize() == 0)) {

            EV << "[DHT::handleLookupResponse()]\n"
               << "    Unable to get replica list : invalid lookup"
               << endl;
            DHTputCAPIResponse* capiPutRespMsg = new DHTputCAPIResponse();
            capiPutRespMsg->setIsSuccess(false);
            sendRpcResponse(capiPutMsg, capiPutRespMsg);
            return;
        }

        for (unsigned int i = 0; i < lookupMsg->getSiblingsArraySize(); i++) {
            DHTPutCall* dhtMsg = new DHTPutCall();
            dhtMsg->setKey(capiPutMsg->getKey());
            dhtMsg->setValue(capiPutMsg->getValue());
            dhtMsg->setKind(capiPutMsg->getKind());
            dhtMsg->setId(capiPutMsg->getId());
            dhtMsg->setTtl(capiPutMsg->getTtl());
            dhtMsg->setIsModifiable(capiPutMsg->getIsModifiable());
            dhtMsg->setMaintenance(false);
            dhtMsg->setBitLength(PUTCALL_L(dhtMsg));
            RECORD_STATS(normalMessages++;
                         numBytesNormal += dhtMsg->getByteLength());
            sendRouteRpcCall(TIER1_COMP, lookupMsg->getSiblings(i),
                             dhtMsg, NULL, DEFAULT_ROUTING, -1,
                             0, capiPutMsg->getNonce());
        }

        PutMapEntry mapEntry;
        mapEntry.callMsg = capiPutMsg;
        mapEntry.numResponses = 0;
        mapEntry.numFailed = 0;
        mapEntry.numSent = lookupMsg->getSiblingsArraySize();

        putMap.insert(make_pair(capiPutMsg->getNonce(), mapEntry));
    }
    else if (dynamic_cast<DHTgetCAPICall*>(it->second)) {

#if 0
        cout << "DHT::handleLookupResponse(): GET "
             << lookupMsg->getKey() << " ("
             << overlay->getThisNode().getKey() << ")" << endl;

        for (unsigned int i = 0; i < lookupMsg->getSiblingsArraySize(); i++) {
            cout << i << ": " << lookupMsg->getSiblings(i) << endl;
        }
#endif

        DHTgetCAPICall* capiGetMsg = dynamic_cast<DHTgetCAPICall*>(it->second);
        rpcIdMap.erase(lookupMsg->getNonce());

        // Invalid lookup
        if ((lookupMsg->getIsValid() == false)
                || (lookupMsg->getSiblingsArraySize() == 0)) {

            EV << "[DHT::handleLookupResponse()]\n"
               << "    Unable to get replica list : invalid lookup"
               << endl;
            DHTgetCAPIResponse* capiGetRespMsg = new DHTgetCAPIResponse();
            //capiGetRespMsg->setKey(lookupMsg->getKey());
            //capiGetRespMsg->setValue(BinaryValue::UNSPECIFIED_VALUE);
            DhtDumpEntry result;
            result.setKey(lookupMsg->getKey());
            result.setValue(BinaryValue::UNSPECIFIED_VALUE);
            capiGetRespMsg->setResultArraySize(1);
            capiGetRespMsg->setResult(0, result);
            capiGetRespMsg->setIsSuccess(false);
            sendRpcResponse(capiGetMsg, capiGetRespMsg);
            return;
        }

        // Valid lookup
        GetMapEntry mapEntry;
        mapEntry.numSent = 0;

        // Multi team version: Already mapEntry from earlier team?

        std::map<int, GetMapEntry>::iterator it2 =
            getMap.find(capiGetMsg->getNonce());

        if (it2 != getMap.end()) {
            mapEntry = it2->second;
        } else {
            mapEntry.teamNumber = 0;
        }
        mapEntry.numAvailableReplica = lookupMsg->getSiblingsArraySize();
        mapEntry.numResponses = 0;
        mapEntry.callMsg = capiGetMsg;
        mapEntry.hashVector = NULL;
        mapEntry.replica.clear();
        for (unsigned int i = 0; i < lookupMsg->getSiblingsArraySize(); i++) {
            // Simplified GET Request: Just one real request, rest is for fallback
            if (i == 0) {
                CBRDHTGetCall* dhtMsg = new CBRDHTGetCall();

                dhtMsg->setOriginalKey(capiGetMsg->getKey());
                dhtMsg->setKey(lookupMsg->getKey());

                dhtMsg->setIsHash(false);
                dhtMsg->setKind(capiGetMsg->getKind());
                dhtMsg->setId(capiGetMsg->getId());
                dhtMsg->setBitLength(GETCALL_L(dhtMsg));
                RECORD_STATS(normalMessages++;
                numBytesNormal += dhtMsg->getByteLength());
                sendRouteRpcCall(TIER1_COMP, lookupMsg->getSiblings(i), dhtMsg,
                                 NULL, DEFAULT_ROUTING, -1, 0,
                                 capiGetMsg->getNonce());
                mapEntry.numSent++;
            } else {
                //We don't send, we just store the remaining keys as fallback
                mapEntry.replica.push_back(lookupMsg->getSiblings(i));
            }
        }
        /*
            std::cout << "New replica: " <<  std::endl;
            for (int i = 0; i < mapEntry.replica.size(); i++) {
                std::cout << mapEntry.replica[i] << std::endl;
            }
            std::cout << "*************************" << std::endl;
         */
        if (it2 != getMap.end())
            getMap.erase(it2);
        getMap.insert(make_pair(capiGetMsg->getNonce(), mapEntry));
    } else if (dynamic_cast<DHTPutCall*>(it->second)) {
        DHTPutCall* putMsg = dynamic_cast<DHTPutCall*>(it->second);
        rpcIdMap.erase(lookupMsg->getNonce());

        if ((lookupMsg->getIsValid() == false)
            || (lookupMsg->getSiblingsArraySize() == 0)) {

            EV << "[DHT::handleLookupResponse()]\n"
               << "    Unable to get replica list : invalid lookup"
               << endl;
            delete putMsg;
            return;
        }

        for( unsigned int i = 0; i < lookupMsg->getSiblingsArraySize(); i++ ) {
            RECORD_STATS(maintenanceMessages++;
                         numBytesMaintenance += putMsg->getByteLength());

            sendRouteRpcCall(TIER1_COMP, lookupMsg->getSiblings(i),
                             new DHTPutCall(*putMsg));
        }

        delete putMsg;
    }
}

void CBRDHT::handlePutCAPIRequest ( DHTputCAPICall capiPutMsg  )  [protected]

Definition at line 375 of file CBR-DHT.cc.

Referenced by handleRpcCall().

{
    // provide copies of this message for other teams
    for (int i = 1; i < numReplicaTeams; i++) {
        DHTPutCall* teamCopyPutMsg = new DHTPutCall; //TODO memleak

        // transfer attributes of original DHTputCAPICall to DHTPutCall for teams
        teamCopyPutMsg->setValue(capiPutMsg->getValue());
        teamCopyPutMsg->setTtl(capiPutMsg->getTtl());
        teamCopyPutMsg->setIsModifiable(capiPutMsg->getIsModifiable());
        teamCopyPutMsg->setKind(capiPutMsg->getKind());
        teamCopyPutMsg->setId(capiPutMsg->getId());

        // control info needs to be copied by value
        OverlayCtrlInfo controlInfo = *(check_and_cast<OverlayCtrlInfo*>(capiPutMsg->getControlInfo()));
        OverlayCtrlInfo* controlInfoCopy = new OverlayCtrlInfo;
        *controlInfoCopy = controlInfo;
        teamCopyPutMsg->setControlInfo(controlInfoCopy);

        // multiple SHA1 hashing of original key
        OverlayKey destKey = capiPutMsg->getKey();
        for (int j = 0; j < i; j++) {
            destKey = OverlayKey::sha1(BinaryValue(destKey.toString(16).c_str()));
        }
        teamCopyPutMsg->setKey(destKey);

        // rest is analog to handlePutCAPIRequest, but for DHTPutCall
        LookupCall* replicaMsg = new LookupCall();
        replicaMsg->setKey(teamCopyPutMsg->getKey());
        replicaMsg->setNumSiblings(floor(numReplica / numReplicaTeams));
        int nonce = sendInternalRpcCall(OVERLAY_COMP, replicaMsg);
        rpcIdMap.insert(make_pair(nonce, teamCopyPutMsg));
    }

    //asks the replica list
    LookupCall* replicaMsg = new LookupCall();
    replicaMsg->setKey(capiPutMsg->getKey());
    replicaMsg->setNumSiblings(floor(numReplica / numReplicaTeams));
    int nonce = sendInternalRpcCall(OVERLAY_COMP, replicaMsg);
    rpcIdMap.insert(make_pair(nonce, capiPutMsg));
}

void CBRDHT::handlePutRequest ( DHTPutCall dhtMsg  )  [protected]

Definition at line 274 of file CBR-DHT.cc.

Referenced by handleRpcCall().

{
    std::string tempString = "PUT_REQUEST received: "
            + std::string(dhtMsg->getKey().toString(16));
    getParentModule()->getParentModule()->bubble(tempString.c_str());

    if (!(dataStorage->isModifiable(dhtMsg->getKey(), dhtMsg->getKind(),
                                    dhtMsg->getId()))) {
        //check if the put request came from the right node
        NodeHandle sourceNode = dataStorage->getSourceNode(dhtMsg->getKey(),
                                                           dhtMsg->getKind(), dhtMsg->getId());
        if (((!sourceNode.isUnspecified())
                && (!dhtMsg->getSrcNode().isUnspecified()) && (sourceNode
                != dhtMsg->getSrcNode())) || ((dhtMsg->getMaintenance())
                && (dhtMsg->getOwnerNode() == sourceNode))) {
            // TODO: set owner
            DHTPutResponse* responseMsg = new DHTPutResponse();
            responseMsg->setSuccess(false);
            responseMsg->setBitLength(PUTRESPONSE_L(responseMsg));
            RECORD_STATS(normalMessages++;
                         numBytesNormal += responseMsg->getByteLength());
            sendRpcResponse(dhtMsg, responseMsg);
            return;
        }

    }

    // remove data item from local data storage
    //cancelAndDelete(dataStorage->getTtlMessage(dhtMsg->getKey()));
    //dataStorage->removeData(dhtMsg->getKey());
    dataStorage->removeData(dhtMsg->getKey(), dhtMsg->getKind(),
                                dhtMsg->getId());
    if (dhtMsg->getValue().size() > 0) {
        // add ttl timer
        DHTTtlTimer *timerMsg = new DHTTtlTimer("ttl_timer");
        timerMsg->setKey(dhtMsg->getKey());
        scheduleAt(simTime() + dhtMsg->getTtl(), timerMsg);
        // storage data item in local data storage
        bool err;
        dataStorage->addData(dhtMsg->getKey(), dhtMsg->getKind(),
                             dhtMsg->getId(), dhtMsg->getValue(), timerMsg,
                             dhtMsg->getIsModifiable(), dhtMsg->getSrcNode(),
                             overlay->isSiblingFor(overlay->getThisNode(),
                                                   dhtMsg->getKey(),
                                                   1, &err));
    }

    // send back
    DHTPutResponse* responseMsg = new DHTPutResponse();

    responseMsg->setSuccess(true);
    responseMsg->setBitLength(PUTRESPONSE_L(responseMsg));
    RECORD_STATS(normalMessages++; numBytesNormal += responseMsg->getByteLength());

    sendRpcResponse(dhtMsg, responseMsg);
}

void CBRDHT::handlePutResponse ( DHTPutResponse dhtMsg,
int  rpcId 
) [protected]

Definition at line 563 of file CBR-DHT.cc.

Referenced by handleRpcResponse().

{
    std::map<int, PutMapEntry>::iterator it2 =
            putMap.find(rpcId);

    if (it2 == putMap.end()) //unknown request
        return;

    if (dhtMsg->getSuccess()) {
        it2->second.numResponses++;
    } else {
        it2->second.numFailed++;
    }

    if (it2->second.numResponses / (double)it2->second.numSent > 0.5) {
        DHTputCAPIResponse* capiPutRespMsg = new DHTputCAPIResponse();
        capiPutRespMsg->setIsSuccess(true);
        sendRpcResponse(it2->second.callMsg, capiPutRespMsg);
        it2->second.callMsg = NULL;
        putMap.erase(rpcId);
    }
}

bool CBRDHT::handleRpcCall ( BaseCallMessage msg  )  [protected]

Definition at line 143 of file CBR-DHT.cc.

{
    // delegate messages
    RPC_SWITCH_START( msg )
        // RPC_DELEGATE( <messageName>[Call|Response], <methodToCall> )
        RPC_DELEGATE( DHTPut, handlePutRequest );
        RPC_DELEGATE( CBRDHTGet, handleGetRequest );
        RPC_DELEGATE( DHTputCAPI, handlePutCAPIRequest ); //requests coming from an upper tier
        RPC_DELEGATE( DHTgetCAPI, handleGetCAPIRequest );
        RPC_DELEGATE( DHTdump, handleDumpDhtRequest );
    RPC_SWITCH_END( )

    return RPC_HANDLED;
}

void CBRDHT::handleRpcResponse ( BaseResponseMessage msg,
cPolymorphic *  context,
int  rpcId,
simtime_t  rtt 
) [protected]

Definition at line 158 of file CBR-DHT.cc.

{
    RPC_SWITCH_START(msg)
        RPC_ON_RESPONSE(DHTPut){
        handlePutResponse(_DHTPutResponse, rpcId);
        EV << "[DHT::handleRpcResponse()]\n"
           << "    DHT Put RPC Response received: id=" << rpcId
           << " msg=" << *_DHTPutResponse << " rtt=" << rtt
           << endl;
        break;
    }
    RPC_ON_RESPONSE(CBRDHTGet) {
        handleGetResponse(_CBRDHTGetResponse, rpcId);
        EV << "[DHT::handleRpcResponse()]\n"
           << "    DHT Get RPC Response received: id=" << rpcId
           << " msg=" << *_CBRDHTGetResponse << " rtt=" << rtt
           << endl;
        break;
    }
    RPC_ON_RESPONSE(Lookup) {
        handleLookupResponse(_LookupResponse);
        EV << "[DHT::handleRpcResponse()]\n"
           << "    Replica Set RPC Response received: id=" << rpcId
           << " msg=" << *_LookupResponse << " rtt=" << rtt
           << endl;
        break;
    }
    RPC_SWITCH_END()
}

void CBRDHT::handleRpcTimeout ( BaseCallMessage msg,
const TransportAddress dest,
cPolymorphic *  context,
int  rpcId,
const OverlayKey destKey 
) [protected]

Definition at line 189 of file CBR-DHT.cc.

{
    RPC_SWITCH_START(msg)
    RPC_ON_CALL(DHTPut){
        EV << "[DHT::handleRpcResponse()]\n"
           << "    DHTPut Timeout"
           << endl;

        std::map<int, PutMapEntry>::iterator it2 =
                putMap.find(rpcId);

        if (it2 == putMap.end()) //unknown request
            return;

        it2->second.numFailed++;

        if (it2->second.numFailed / (double)it2->second.numSent >= 0.5) {
            DHTputCAPIResponse* capiPutRespMsg = new DHTputCAPIResponse();
            capiPutRespMsg->setIsSuccess(false);
            sendRpcResponse(it2->second.callMsg, capiPutRespMsg);
            it2->second.callMsg = NULL;
            putMap.erase(rpcId);
        }
        break;
    }
    RPC_ON_CALL(CBRDHTGet) {
        EV << "[DHT::handleRpcResponse()]\n"
           << "    DHTGet Timeout"
           << endl;

        std::map<int, GetMapEntry>::iterator it2 =
            getMap.find(rpcId);

        if (it2 == getMap.end()) //unknown request
            return;

        if (it2->second.replica.size() > 0) {
            // Received empty value, try fallback replica
            NodeHandle fallbackReplica = it2->second.replica.back();
            CBRDHTGetCall* dhtRecall = new CBRDHTGetCall();
            dhtRecall->setOriginalKey(_CBRDHTGetCall->getOriginalKey());
            dhtRecall->setKey(_CBRDHTGetCall->getKey());
            dhtRecall->setIsHash(false);
            dhtRecall->setBitLength(GETCALL_L(dhtRecall));
            RECORD_STATS(normalMessages++;
            numBytesNormal += dhtRecall->getByteLength());
            sendRouteRpcCall(TIER1_COMP, fallbackReplica, dhtRecall,
                             NULL, DEFAULT_ROUTING, -1, 0,
                             it2->second.callMsg->getNonce());
            it2->second.numSent++;
            it2->second.replica.pop_back();
            return;
        } else if (it2->second.teamNumber < (numReplicaTeams - 1)) {
            // No more fallback replica in this team, try next one
            it2->second.teamNumber++;
            handleGetCAPIRequest(it2->second.callMsg, it2->second.teamNumber);
            return;
        } else {
            // No more replica, no more teams, send success == false to Tier 2 :(
            DHTgetCAPIResponse* capiGetRespMsg = new DHTgetCAPIResponse();
            //capiGetRespMsg->setKey(_CBRDHTGetCall->getOriginalKey());
            //capiGetRespMsg->setValue(BinaryValue::UNSPECIFIED_VALUE);
            DhtDumpEntry result;
            result.setKey(_CBRDHTGetCall->getKey());
            result.setValue(BinaryValue::UNSPECIFIED_VALUE);
            capiGetRespMsg->setResultArraySize(1);
            capiGetRespMsg->setResult(0, result);
            capiGetRespMsg->setIsSuccess(false);
            sendRpcResponse(it2->second.callMsg, capiGetRespMsg);
            getMap.erase(rpcId);
        }
        break;
    }
    RPC_SWITCH_END( )
}

void CBRDHT::handleTimerEvent ( cMessage *  msg  )  [protected]

Definition at line 109 of file CBR-DHT.cc.

{
    DHTTtlTimer* msg_timer = dynamic_cast<DHTTtlTimer*> (msg);

    if (msg_timer) {
        EV << "[DHT::handleTimerEvent()]\n"
           << "    received timer ttl, key: "
           << msg_timer->getKey().toString(16)
           << "\n (overlay->getThisNode().key = "
           << overlay->getThisNode().getKey().toString(16) << ")"
           << endl;

        dataStorage->removeData(msg_timer->getKey(), msg_timer->getKind(),
                                msg_timer->getId());
        //delete msg_timer;
    }
    /*DHTTtlTimer* msg_timer;

    if (msg->isName("ttl_timer")) {
        msg_timer = check_and_cast<DHTTtlTimer*> (msg);

        EV << "[DHT::handleTimerEvent()]\n"
           << "    received timer ttl, key: "
           << msg_timer->getKey().toString(16)
           << "\n (overlay->getThisNode().key = "
           << overlay->getThisNode().getKey().toString(16) << ")"
           << endl;

        dataStorage->removeData(msg_timer->getKey(), msg_timer->getKind(),
                                msg_timer->getId());
        delete msg_timer;
    }*/
}

void CBRDHT::handleUpperMessage ( cMessage *  msg  )  [protected, virtual]

handleUpperMessage gets called of handleMessage(cMessage* msg) if msg arrivedOn from_upperTier (currently msg gets deleted in this function)

Parameters:
msg the message to handle

Reimplemented from BaseApp.

Definition at line 267 of file CBR-DHT.cc.

{
    error("DHT::handleUpperMessage(): Received message with unknown type!");

    delete msg;
}

void CBRDHT::initializeApp ( int  stage  )  [protected, virtual]

initializes derived class-attributes

Parameters:
stage the init stage

Reimplemented from BaseApp.

Definition at line 78 of file CBR-DHT.cc.

{
        if (stage != MIN_STAGE_APP)
        return;

    dataStorage = check_and_cast<DHTDataStorage*>
                      (getParentModule()->getSubmodule("dhtDataStorage"));

    coordBasedRouting = CoordBasedRoutingAccess().get();
    neighborCache = (NeighborCache*)getParentModule()
        ->getParentModule()->getSubmodule("neighborCache");

    numReplica = par("numReplica");
    numReplicaTeams = par("numReplicaTeams");

    if (numReplica > numReplicaTeams * overlay->getMaxNumSiblings()) {
        opp_error("DHT::initialize(): numReplica bigger than what this "
                  "overlay can handle (%d)", numReplicaTeams*overlay->getMaxNumSiblings());
    }

    maintenanceMessages = 0;
    normalMessages = 0;
    numBytesMaintenance = 0;
    numBytesNormal = 0;
    WATCH(maintenanceMessages);
    WATCH(normalMessages);
    WATCH(numBytesNormal);
    WATCH(numBytesMaintenance);
    WATCH_MAP(rpcIdMap);
}

int CBRDHT::resultValuesBitLength ( DHTGetResponse msg  )  [protected]

Definition at line 928 of file CBR-DHT.cc.

                                                     {
    int bitSize = 0;
    for (uint i = 0; i < msg->getResultArraySize(); i++) {
        bitSize += msg->getResult(i).getValue().size();

    }
    return bitSize;
}

void CBRDHT::update ( const NodeHandle node,
bool  joined 
) [protected, virtual]

Common API function: informs application about neighbors and own nodeID.

Parameters:
node new or lost neighbor
joined new or lost?

Reimplemented from BaseApp.

Definition at line 668 of file CBR-DHT.cc.

{
    OverlayKey key;
    DHTPutCall* dhtMsg;
    bool err = false;
    //DHTData entry;
    DhtDataEntry entry;
    //std::map<OverlayKey, DHTData>::iterator it = dataStorage->begin();
    DhtDataMap::iterator it = dataStorage->begin();
    for (unsigned int i = 0; i < dataStorage->getSize(); i++) {
        key = it->first;
        entry = it->second;
        if (joined) {
            if (entry.responsible && (overlay->isSiblingFor(node, key,
                                                            numReplica, &err)
                    || err)) { // hack for Chord, if we've got a new predecessor

                dhtMsg = new DHTPutCall();
                dhtMsg->setKey(key);
                dhtMsg->setValue(entry.value);
                dhtMsg->setKind(entry.kind);
                dhtMsg->setId(entry.id);

                //dhtMsg->setTtl((int) (entry.ttlMessage->arrivalTime()
                //        - simTime()));
                dhtMsg->setTtl((int)SIMTIME_DBL(entry.ttlMessage->getArrivalTime()
                                                - simTime()));
                dhtMsg->setIsModifiable(entry.is_modifiable);
                dhtMsg->setMaintenance(true);
                dhtMsg->setBitLength(PUTCALL_L(dhtMsg));
                RECORD_STATS(maintenanceMessages++;
                        numBytesMaintenance += dhtMsg->getByteLength());
                sendRouteRpcCall(TIER1_COMP, node, dhtMsg);
            }

            if (err) {
                EV << "[DHT::update()]\n"
                   << "    Unable to know if key: " << key
                   << " is in range of node: " << node
                   << endl;
            }
        } else {
#if 0
            //the update concerns a node who has left
            //replicate
            LookupCall* replicaMsg = new LookupCall();
            replicaMsg->setKey(key);
            replicaMsg->setNumSiblings(numReplica);
            int nonce = sendInternalRpcCall(OVERLAY_COMP,
                                            replicaMsg);
            dhtMsg = new DHTPutCall();
            dhtMsg->setKey(key);
            dhtMsg->setValue(entry.value);
            dhtMsg->setTtl((int)(entry.ttlMessage->arrivalTime()
                    - simulation.simTime()));
            dhtMsg->setIsModifiable(entry.is_modifiable);
            dhtMsg->setMaintenance(true);
            dhtMsg->setLength(PUTCALL_L(dhtMsg));

            rpcIdMap.insert(make_pair(nonce, dhtMsg));
#endif
        }

        entry.responsible = overlay->isSiblingFor(overlay->getThisNode(),
                                                  key, 1, &err);
        it++;
    }
}


Member Data Documentation

Definition at line 116 of file CBR-DHT.h.

Referenced by handleGetCAPIRequest(), and initializeApp().

pointer to the dht data storage

Definition at line 115 of file CBR-DHT.h.

Referenced by CBRDHT(), handleDumpDhtRequest(), handleGetRequest(), handlePutRequest(), handleTimerEvent(), initializeApp(), update(), and ~CBRDHT().

std::map<int, GetMapEntry> CBRDHT::getMap [protected]
double CBRDHT::lastGetCall [protected]

Definition at line 109 of file CBR-DHT.h.

Referenced by handleGetCAPIRequest().

double CBRDHT::maintenanceMessages [protected]

Definition at line 105 of file CBR-DHT.h.

Referenced by finishApp(), handleLookupResponse(), initializeApp(), and update().

Definition at line 117 of file CBR-DHT.h.

Referenced by handleGetCAPIRequest(), and initializeApp().

double CBRDHT::numBytesMaintenance [protected]

Definition at line 107 of file CBR-DHT.h.

Referenced by finishApp(), handleLookupResponse(), initializeApp(), and update().

int CBRDHT::numReplica [protected]

Definition at line 102 of file CBR-DHT.h.

Referenced by handleGetCAPIRequest(), handlePutCAPIRequest(), initializeApp(), and update().

std::map<int, PutMapEntry> CBRDHT::putMap [protected]

Definition at line 112 of file CBR-DHT.h.

Referenced by handleLookupResponse(), handlePutResponse(), handleRpcTimeout(), and ~CBRDHT().

std::map<unsigned int, BaseCallMessage*> CBRDHT::rpcIdMap [protected]

List of the Rpc Ids of the messages sent following the reception of an rpc request (the second member).

Definition at line 110 of file CBR-DHT.h.

Referenced by handleGetCAPIRequest(), handleGetRequest(), handleGetResponse(), handleLookupResponse(), handlePutCAPIRequest(), initializeApp(), update(), and ~CBRDHT().


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