DHT Class Reference

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

#include <DHT.h>

Inheritance diagram for DHT:

BaseApp BaseRpc RpcListener

List of all members.

Classes

struct  GetMapEntry
struct  PutMapEntry

Public Member Functions

 DHT ()
virtual ~DHT ()

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)
 Processes Remote-Procedure-Call invocation messages.
void handleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt)
 This method is called if an RPC response has been received.
void handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, cPolymorphic *context, int rpcId, const OverlayKey &destKey)
 This method is called if an RPC timeout has been reached.
void handlePutRequest (DHTPutCall *dhtMsg)
void handleGetRequest (DHTGetCall *dhtMsg)
void handlePutResponse (DHTPutResponse *dhtMsg, int rpcId)
void handleGetResponse (DHTGetResponse *dhtMsg, int rpcId)
void handlePutCAPIRequest (DHTputCAPICall *capiPutMsg)
void handleGetCAPIRequest (DHTgetCAPICall *capiPutMsg)
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)

Protected Attributes

int numReplica
int numGetRequests
double ratioIdentical
double maintenanceMessages
double normalMessages
double numBytesMaintenance
double numBytesNormal
simtime_t 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

Private Member Functions

int resultValuesBitLength (DHTGetResponse *msg)


Detailed Description

A Distributed Hash Table (DHT) for KBR protocols.

A Distributed Hash Table (DHT) for KBR protocols

Definition at line 44 of file DHT.h.


Member Typedef Documentation

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

Definition at line 51 of file DHT.h.


Constructor & Destructor Documentation

DHT::DHT (  ) 

Definition at line 36 of file DHT.cc.

00037 {
00038     dataStorage = NULL;
00039 }

DHT::~DHT (  )  [virtual]

Definition at line 41 of file DHT.cc.

00042 {
00043     std::map<unsigned int, BaseCallMessage*>::iterator it;
00044 
00045     for (it = rpcIdMap.begin(); it != rpcIdMap.end(); it++) {
00046         cancelAndDelete(it->second);
00047         it->second = NULL;
00048     }
00049 
00050     std::map<int, GetMapEntry>::iterator it2;
00051 
00052     for (it2 = getMap.begin(); it2 != getMap.end(); it2++) {
00053         cancelAndDelete(it2->second.callMsg);
00054         it2->second.callMsg = NULL;
00055     }
00056 
00057     std::map<int, PutMapEntry>::iterator it3;
00058 
00059     for (it3 = putMap.begin(); it3 != putMap.end(); it3++) {
00060         cancelAndDelete(it3->second.callMsg);
00061         it3->second.callMsg = NULL;
00062     }
00063 
00064     rpcIdMap.clear();
00065     getMap.clear();
00066     putMap.clear();
00067 
00068     if (dataStorage != NULL) {
00069         dataStorage->clear();
00070     }
00071 }


Member Function Documentation

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

collects statistical data of derived app

Reimplemented from BaseApp.

Definition at line 831 of file DHT.cc.

00832 {
00833     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00834 
00835     if (time >= GlobalStatistics::MIN_MEASURED) {
00836         globalStatistics->addStdDev("DHT: Sent Maintenance Messages/s",
00837                                     maintenanceMessages / time);
00838         globalStatistics->addStdDev("DHT: Sent Normal Messages/s",
00839                                     normalMessages / time);
00840         globalStatistics->addStdDev("DHT: Sent Maintenance Bytes/s",
00841                                     numBytesMaintenance / time);
00842         globalStatistics->addStdDev("DHT: Sent Normal Bytes/s",
00843                                     numBytesNormal / time);
00844     }
00845 }

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

Definition at line 450 of file DHT.cc.

Referenced by handleRpcCall().

00451 {
00452     DHTdumpResponse* response = new DHTdumpResponse();
00453     DhtDumpVector* dumpVector = dataStorage->dumpDht();
00454 
00455     response->setRecordArraySize(dumpVector->size());
00456 
00457     for (uint32_t i = 0; i < dumpVector->size(); i++) {
00458         response->setRecord(i, (*dumpVector)[i]);
00459     }
00460 
00461     delete dumpVector;
00462 
00463     sendRpcResponse(call, response);
00464 }

void DHT::handleGetCAPIRequest ( DHTgetCAPICall capiPutMsg  )  [protected]

Definition at line 440 of file DHT.cc.

Referenced by handleRpcCall().

00441 {
00442     LookupCall* replicaMsg = new LookupCall();
00443     replicaMsg->setKey(capiGetMsg->getKey());
00444     replicaMsg->setNumSiblings(numReplica);
00445     int nonce = sendInternalRpcCall(OVERLAY_COMP, replicaMsg);
00446     rpcIdMap.insert(make_pair(nonce, capiGetMsg));
00447     lastGetCall = simTime();
00448 }

void DHT::handleGetRequest ( DHTGetCall dhtMsg  )  [protected]

Definition at line 372 of file DHT.cc.

Referenced by handleRpcCall().

00373 {
00374     std::string tempString = "GET_REQUEST received: "
00375             + std::string(dhtMsg->getKey().toString(16));
00376 
00377     getParentModule()->getParentModule()->bubble(tempString.c_str());
00378 
00379     if (dhtMsg->getKey().isUnspecified()) {
00380         throw cRuntimeError("DHT::handleGetRequest: Unspecified key!");
00381     }
00382 
00383     DhtDumpVector* dataVect = dataStorage->dumpDht(dhtMsg->getKey(),
00384                                                    dhtMsg->getKind(),
00385                                                    dhtMsg->getId());
00386 
00387     // send back
00388     DHTGetResponse* responseMsg = new DHTGetResponse();
00389     responseMsg->setKey(dhtMsg->getKey());
00390     responseMsg->setIsHash(dhtMsg->getIsHash());
00391 
00392     if (dataVect->size() == 0) {
00393         responseMsg->setHashValue(BinaryValue::UNSPECIFIED_VALUE);
00394         responseMsg->setResultArraySize(0);
00395     } else {
00396         if (dhtMsg->getIsHash()) {
00397             // TODO: verify this
00398             BinaryValue resultValues;
00399             for (uint32_t i = 0; i < dataVect->size(); i++) {
00400                 resultValues += (*dataVect)[i].getValue();
00401             }
00402 
00403             CSHA1 sha1;
00404             BinaryValue hashValue(20);
00405             sha1.Reset();
00406             sha1.Update((uint8_t*) (&(*resultValues.begin())),
00407                         resultValues.size());
00408             sha1.Final();
00409             sha1.GetHash((unsigned char*)&hashValue[0]);
00410 
00411             responseMsg->setHashValue(hashValue);
00412         } else {
00413             responseMsg->setResultArraySize(dataVect->size());
00414 
00415             for (uint32_t i = 0; i < dataVect->size(); i++) {
00416                 responseMsg->setResult(i, (*dataVect)[i]);
00417             }
00418 
00419         }
00420 
00421         delete dataVect;
00422     }
00423 
00424     responseMsg->setBitLength(GETRESPONSE_L(responseMsg));
00425     RECORD_STATS(normalMessages++;
00426                  numBytesNormal += responseMsg->getByteLength());
00427     sendRpcResponse(dhtMsg, responseMsg);
00428 }

void DHT::handleGetResponse ( DHTGetResponse dhtMsg,
int  rpcId 
) [protected]

Definition at line 487 of file DHT.cc.

Referenced by handleRpcResponse().

00488 {
00489     std::map<unsigned int, BaseCallMessage*>::iterator it =
00490             rpcIdMap.find(dhtMsg->getNonce());
00491     std::map<int, GetMapEntry>::iterator it2 =
00492             getMap.find(rpcId);
00493 
00494     if (it2 == getMap.end()) //unknown request
00495         return;
00496 
00497     if (it != rpcIdMap.end()) {
00498         //we have sent a 'real' get request
00499         rpcIdMap.erase(dhtMsg->getNonce());
00500         if (!dhtMsg->getIsHash()) {
00501             // TODO verify hash
00502             DHTgetCAPIResponse* capiGetRespMsg = new DHTgetCAPIResponse();
00503             capiGetRespMsg->setResultArraySize(dhtMsg->getResultArraySize());
00504             for (uint i = 0; i < dhtMsg->getResultArraySize(); i++) {
00505                 capiGetRespMsg->setResult(i, dhtMsg->getResult(i));
00506             }
00507             capiGetRespMsg->setIsSuccess(true);
00508             sendRpcResponse(it2->second.callMsg, capiGetRespMsg);
00509             getMap.erase(rpcId);
00510             return;
00511         }
00512     } else {
00513         if (dhtMsg->getIsHash()) {
00514             std::map<BinaryValue, ReplicaVector>::iterator itHashes =
00515                     it2->second.hashes.find(dhtMsg->getHashValue());
00516 
00517             if (itHashes == it2->second.hashes.end()) {
00518                 //new hash
00519                 ReplicaVector vect = ReplicaVector();
00520                 vect.push_back(dhtMsg->getSrcNode());
00521                 it2->second.hashes.insert(make_pair(dhtMsg->getHashValue(),
00522                                                     vect));
00523             } else {
00524                 itHashes->second.push_back(dhtMsg->getSrcNode());
00525             }
00526 
00527             it2->second.numResponses++;
00528 
00529             //we've got all the answers we wanted
00530             unsigned int maxCount = 0;
00531             ReplicaVector* hashVector = NULL;
00532             for (itHashes = it2->second.hashes.begin(); itHashes
00533             != it2->second.hashes.end(); itHashes++) {
00534                 if (itHashes->second.size() > maxCount) {
00535                     maxCount = itHashes->second.size();
00536                     hashVector = &(itHashes->second);
00537                 }
00538             }
00539 
00540             if ((double) maxCount / (double) it2->second.numAvailableReplica
00541                     >= ratioIdentical) {
00542                 it2->second.hashVector = hashVector;
00543             } else if (it2->second.numResponses >= numGetRequests){
00544                 //we'll try to ask some other nodes
00545                 if (it2->second.replica.size() > 0) {
00546                     DHTGetCall* getCall = new DHTGetCall();
00547                     getCall->setKey(dhtMsg->getKey());
00548                     getCall->setKind(dhtMsg->getKind());
00549                     getCall->setId(dhtMsg->getId());
00550                     getCall->setIsHash(true);
00551                     getCall->setBitLength(GETCALL_L(getCall));
00552                     RECORD_STATS(normalMessages++;
00553                                      numBytesNormal += getCall->getByteLength());
00554                     sendRouteRpcCall(TIER1_COMP,
00555                                      it2->second.replica.back(), getCall,
00556                                      NULL, DEFAULT_ROUTING, -1, 0,
00557                                      it2->second.callMsg->getNonce());
00558                     it2->second.replica.pop_back();
00559                 } else { //we don't have anyone else to ask
00560                     DHTgetCAPIResponse* capiGetRespMsg =
00561                         new DHTgetCAPIResponse();
00562                     DhtDumpEntry result;
00563                     result.setKey(dhtMsg->getKey());
00564                     result.setValue(BinaryValue::UNSPECIFIED_VALUE);
00565                     capiGetRespMsg->setResultArraySize(1);
00566                     capiGetRespMsg->setResult(0, result);
00567                     capiGetRespMsg->setIsSuccess(false);
00568                     sendRpcResponse(it2->second.callMsg, capiGetRespMsg);
00569                     //cout << "DHT: GET failed: hash (no one else)" << endl;
00570                     getMap.erase(rpcId);
00571                     return;
00572                 }
00573 
00574             }
00575         }
00576     }
00577 
00578     if (it2->second.hashVector != NULL) {
00579         //we have already received all the response and chosen a hash
00580         if (it2->second.hashVector->size() > 0) {
00581             DHTGetCall* getCall = new DHTGetCall();
00582             getCall->setKey(it2->second.callMsg->getKey());
00583             getCall->setKind(it2->second.callMsg->getKind());
00584             getCall->setId(it2->second.callMsg->getId());
00585             getCall->setIsHash(false);
00586             getCall->setBitLength(GETCALL_L(getCall));
00587             RECORD_STATS(normalMessages++;
00588                          numBytesNormal += getCall->getByteLength());
00589             int nonce = sendRouteRpcCall(TIER1_COMP,
00590                                          it2->second.hashVector->back(),
00591                                          getCall, NULL, DEFAULT_ROUTING,
00592                                          -1, 0, it2->second.callMsg->getNonce());
00593             rpcIdMap.insert(make_pair(nonce, (BaseCallMessage*)NULL));
00594             it2->second.hashVector->pop_back();
00595         } else { //we don't have anyone else to ask
00596             DHTgetCAPIResponse* capiGetRespMsg = new DHTgetCAPIResponse();
00597             DhtDumpEntry result;
00598             result.setKey(dhtMsg->getKey());
00599             result.setValue(BinaryValue::UNSPECIFIED_VALUE);
00600             capiGetRespMsg->setResultArraySize(1);
00601             capiGetRespMsg->setResult(0, result);
00602             capiGetRespMsg->setIsSuccess(false);
00603             sendRpcResponse(it2->second.callMsg, capiGetRespMsg);
00604             //cout << "DHT: GET failed: hash2 (no one else)" << endl;
00605             getMap.erase(rpcId);
00606         }
00607     }
00608 }

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

Definition at line 674 of file DHT.cc.

Referenced by handleRpcResponse().

00675 {
00676     std::map<unsigned int, BaseCallMessage*>::iterator it =
00677             rpcIdMap.find(lookupMsg->getNonce());
00678 
00679     if (it == rpcIdMap.end() || it->second == NULL)
00680         return;
00681 
00682     if (dynamic_cast<DHTputCAPICall*> (it->second)) {
00683 
00684         #if 0
00685         cout << "DHT::handleLookupResponse(): PUT "
00686              << lookupMsg->getKey() << " ("
00687              << overlay->getThisNode().getKey() << ")" << endl;
00688 
00689         for (unsigned int i = 0; i < lookupMsg->getSiblingsArraySize(); i++) {
00690             cout << i << ": " << lookupMsg->getSiblings(i) << endl;
00691         }
00692 #endif
00693 
00694         DHTputCAPICall* capiPutMsg = dynamic_cast<DHTputCAPICall*> (it->second);
00695         rpcIdMap.erase(lookupMsg->getNonce());
00696 
00697         if ((lookupMsg->getIsValid() == false)
00698                 || (lookupMsg->getSiblingsArraySize() == 0)) {
00699 
00700             EV << "[DHT::handleLookupResponse()]\n"
00701                << "    Unable to get replica list : invalid lookup"
00702                << endl;
00703             DHTputCAPIResponse* capiPutRespMsg = new DHTputCAPIResponse();
00704             capiPutRespMsg->setKey(lookupMsg->getKey());
00705             capiPutRespMsg->setIsSuccess(false);
00706             //cout << "DHT::lookup failed" << endl;
00707             sendRpcResponse(capiPutMsg, capiPutRespMsg);
00708             return;
00709         }
00710 
00711         if ((capiPutMsg->getId() == 0) && (capiPutMsg->getValue().size() > 0)) {
00712             // pick a random id before replication of the data item
00713             // id 0 is kept for delete requests (i.e. size = 0)
00714             capiPutMsg->setId(intuniform(1, 2147483647));
00715         }
00716 
00717         for (unsigned int i = 0; i < lookupMsg->getSiblingsArraySize(); i++) {
00718             DHTPutCall* dhtMsg = new DHTPutCall();
00719             dhtMsg->setKey(capiPutMsg->getKey());
00720             dhtMsg->setKind(capiPutMsg->getKind());
00721             dhtMsg->setId(capiPutMsg->getId());
00722             dhtMsg->setValue(capiPutMsg->getValue());
00723             dhtMsg->setTtl(capiPutMsg->getTtl());
00724             dhtMsg->setIsModifiable(capiPutMsg->getIsModifiable());
00725             dhtMsg->setMaintenance(false);
00726             dhtMsg->setBitLength(PUTCALL_L(dhtMsg));
00727             RECORD_STATS(normalMessages++;
00728                          numBytesNormal += dhtMsg->getByteLength());
00729             sendRouteRpcCall(TIER1_COMP, lookupMsg->getSiblings(i),
00730                              dhtMsg, NULL, DEFAULT_ROUTING, -1,
00731                              0, capiPutMsg->getNonce());
00732         }
00733 
00734         PutMapEntry mapEntry;
00735         mapEntry.callMsg = capiPutMsg;
00736         mapEntry.numResponses = 0;
00737         mapEntry.numFailed = 0;
00738         mapEntry.numSent = lookupMsg->getSiblingsArraySize();
00739 
00740         putMap.insert(make_pair(capiPutMsg->getNonce(), mapEntry));
00741     }
00742     else if (dynamic_cast<DHTgetCAPICall*>(it->second)) {
00743 
00744 #if 0
00745         cout << "DHT::handleLookupResponse(): GET "
00746              << lookupMsg->getKey() << " ("
00747              << overlay->getThisNode().getKey() << ")" << endl;
00748 
00749         for (unsigned int i = 0; i < lookupMsg->getSiblingsArraySize(); i++) {
00750             cout << i << ": " << lookupMsg->getSiblings(i) << endl;
00751         }
00752 #endif
00753 
00754         DHTgetCAPICall* capiGetMsg = dynamic_cast<DHTgetCAPICall*>(it->second);
00755         rpcIdMap.erase(lookupMsg->getNonce());
00756 
00757         if ((lookupMsg->getIsValid() == false)
00758                 || (lookupMsg->getSiblingsArraySize() == 0)) {
00759 
00760             EV << "[DHT::handleLookupResponse()]\n"
00761                << "    Unable to get replica list : invalid lookup"
00762                << endl;
00763             DHTgetCAPIResponse* capiGetRespMsg = new DHTgetCAPIResponse();
00764             DhtDumpEntry result;
00765             result.setKey(lookupMsg->getKey());
00766             result.setValue(BinaryValue::UNSPECIFIED_VALUE);
00767             capiGetRespMsg->setResultArraySize(1);
00768             capiGetRespMsg->setResult(0, result);
00769             capiGetRespMsg->setIsSuccess(false);
00770             //cout << "DHT: lookup failed 2" << endl;
00771             sendRpcResponse(capiGetMsg, capiGetRespMsg);
00772             return;
00773         }
00774 
00775         GetMapEntry mapEntry;
00776         mapEntry.numSent = 0;
00777 
00778         for (unsigned int i = 0; i < lookupMsg->getSiblingsArraySize(); i++) {
00779             if (i < (unsigned int)numGetRequests) {
00780                 DHTGetCall* dhtMsg = new DHTGetCall();
00781                 dhtMsg->setKey(capiGetMsg->getKey());
00782                 dhtMsg->setKind(capiGetMsg->getKind());
00783                 dhtMsg->setId(capiGetMsg->getId());
00784                 dhtMsg->setIsHash(true);
00785                 dhtMsg->setBitLength(GETCALL_L(dhtMsg));
00786                 RECORD_STATS(normalMessages++;
00787                              numBytesNormal += dhtMsg->getByteLength());
00788                 sendRouteRpcCall(TIER1_COMP, lookupMsg->getSiblings(i), dhtMsg,
00789                                  NULL, DEFAULT_ROUTING, -1, 0,
00790                                  capiGetMsg->getNonce());
00791                 mapEntry.numSent++;
00792             } else {
00793                 //We don't send, we just store the remaining keys
00794                 mapEntry.replica.push_back(lookupMsg->getSiblings(i));
00795             }
00796         }
00797 
00798         mapEntry.numAvailableReplica = lookupMsg->getSiblingsArraySize();
00799         mapEntry.callMsg = capiGetMsg;
00800         mapEntry.numResponses = 0;
00801         mapEntry.hashVector = NULL;
00802 
00803         getMap.insert(make_pair(capiGetMsg->getNonce(), mapEntry));
00804     }
00805     else if (dynamic_cast<DHTPutCall*>(it->second)) {
00806         DHTPutCall* putMsg = dynamic_cast<DHTPutCall*>(it->second);
00807         rpcIdMap.erase(lookupMsg->getNonce());
00808 
00809         if ((lookupMsg->getIsValid() == false)
00810                 || (lookupMsg->getSiblingsArraySize() == 0)) {
00811 
00812             EV << "[DHT::handleLookupResponse()]\n"
00813                << "    Unable to get replica list : invalid lookup"
00814                << endl;
00815             delete putMsg;
00816             return;
00817         }
00818 
00819         for( unsigned int i = 0; i < lookupMsg->getSiblingsArraySize(); i++ ) {
00820             RECORD_STATS(maintenanceMessages++;
00821                          numBytesMaintenance += putMsg->getByteLength());
00822 
00823             sendRouteRpcCall(TIER1_COMP, lookupMsg->getSiblings(i),
00824                              new DHTPutCall(*putMsg));
00825         }
00826 
00827         delete putMsg;
00828     }
00829 }

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

Definition at line 430 of file DHT.cc.

Referenced by handleRpcCall().

00431 {
00432     //asks the replica list
00433     LookupCall* replicaMsg = new LookupCall();
00434     replicaMsg->setKey(capiPutMsg->getKey());
00435     replicaMsg->setNumSiblings(numReplica);
00436     int nonce = sendInternalRpcCall(OVERLAY_COMP, replicaMsg);
00437     rpcIdMap.insert(make_pair(nonce, capiPutMsg));
00438 }

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

Definition at line 312 of file DHT.cc.

Referenced by handleRpcCall().

00313 {
00314     std::string tempString = "PUT_REQUEST received: "
00315             + std::string(dhtMsg->getKey().toString(16));
00316     getParentModule()->getParentModule()->bubble(tempString.c_str());
00317 
00318     if (!(dataStorage->isModifiable(dhtMsg->getKey(), dhtMsg->getKind(),
00319                                     dhtMsg->getId()))) {
00320         // check if the put request came from the right node
00321         NodeHandle sourceNode = dataStorage->getSourceNode(dhtMsg->getKey(),
00322                                     dhtMsg->getKind(), dhtMsg->getId());
00323         if (((!sourceNode.isUnspecified())
00324                 && (!dhtMsg->getSrcNode().isUnspecified()) && (sourceNode
00325                 != dhtMsg->getSrcNode())) || ((dhtMsg->getMaintenance())
00326                 && (dhtMsg->getOwnerNode() == sourceNode))) {
00327             // TODO: set owner
00328             DHTPutResponse* responseMsg = new DHTPutResponse();
00329             responseMsg->setKey(dhtMsg->getKey());
00330             tempString = "Error, not allowed to modify this key";
00331             responseMsg->setValue(BinaryValue(tempString));
00332             responseMsg->setBitLength(PUTRESPONSE_L(responseMsg));
00333             RECORD_STATS(normalMessages++;
00334                          numBytesNormal += responseMsg->getByteLength());
00335             sendRpcResponse(dhtMsg, responseMsg);
00336             return;
00337         }
00338 
00339     }
00340 
00341     // remove data item from local data storage
00342     dataStorage->removeData(dhtMsg->getKey(), dhtMsg->getKind(),
00343                             dhtMsg->getId());
00344 
00345     if (dhtMsg->getValue().size() > 0) {
00346         // add ttl timer
00347         DHTTtlTimer *timerMsg = new DHTTtlTimer("ttl_timer");
00348         timerMsg->setKey(dhtMsg->getKey());
00349         timerMsg->setKind(dhtMsg->getKind());
00350         timerMsg->setId(dhtMsg->getId());
00351         scheduleAt(simTime() + dhtMsg->getTtl(), timerMsg);
00352         // storage data item in local data storage
00353         bool err;
00354         dataStorage->addData(dhtMsg->getKey(), dhtMsg->getKind(),
00355                                      dhtMsg->getId(), dhtMsg->getValue(), timerMsg,
00356                              dhtMsg->getIsModifiable(), dhtMsg->getSrcNode(),
00357                              overlay->isSiblingFor(overlay->getThisNode(),
00358                                                    dhtMsg->getKey(),
00359                                                    1, &err));
00360     }
00361 
00362     // send back
00363     DHTPutResponse* responseMsg = new DHTPutResponse();
00364     responseMsg->setKey(dhtMsg->getKey());
00365     responseMsg->setValue(dhtMsg->getValue());
00366     responseMsg->setBitLength(PUTRESPONSE_L(responseMsg));
00367     RECORD_STATS(normalMessages++; numBytesNormal += responseMsg->getByteLength());
00368 
00369     sendRpcResponse(dhtMsg, responseMsg);
00370 }

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

Definition at line 466 of file DHT.cc.

Referenced by handleRpcResponse().

00467 {
00468     std::map<int, PutMapEntry>::iterator it2 =
00469             putMap.find(rpcId);
00470 
00471     if (it2 == putMap.end()) //unknown request
00472         return;
00473 
00474     it2->second.numResponses++;
00475 
00476     if (it2->second.numResponses / (double)it2->second.numSent > 0.5) {
00477         DHTputCAPIResponse* capiPutRespMsg = new DHTputCAPIResponse();
00478         capiPutRespMsg->setKey(dhtMsg->getKey());
00479         capiPutRespMsg->setValue(dhtMsg->getValue());
00480         capiPutRespMsg->setIsSuccess(true);
00481         sendRpcResponse(it2->second.callMsg, capiPutRespMsg);
00482         it2->second.callMsg = NULL;
00483         putMap.erase(rpcId);
00484     }
00485 }

bool DHT::handleRpcCall ( BaseCallMessage msg  )  [protected, virtual]

Processes Remote-Procedure-Call invocation messages.


This method should be overloaded when the overlay provides RPC functionality.

Returns:
true, if rpc has been handled

Reimplemented from BaseRpc.

Definition at line 118 of file DHT.cc.

00119 {
00120     // delegate messages
00121     RPC_SWITCH_START( msg )
00122         // RPC_DELEGATE( <messageName>[Call|Response], <methodToCall> )
00123         RPC_DELEGATE( DHTPut, handlePutRequest );
00124         RPC_DELEGATE( DHTGet, handleGetRequest );
00125         RPC_DELEGATE( DHTputCAPI, handlePutCAPIRequest ); //requests coming from an upper tier
00126         RPC_DELEGATE( DHTgetCAPI, handleGetCAPIRequest );
00127         RPC_DELEGATE( DHTdump, handleDumpDhtRequest );
00128     RPC_SWITCH_END( )
00129 
00130     return RPC_HANDLED;
00131 }

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

This method is called if an RPC response has been received.

Parameters:
msg The response message.
context Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code
rpcId The RPC id.
rtt The Round-Trip-Time of this RPC

Reimplemented from RpcListener.

Definition at line 133 of file DHT.cc.

00135 {
00136     RPC_SWITCH_START(msg)
00137         RPC_ON_RESPONSE(DHTPut){
00138         handlePutResponse(_DHTPutResponse, rpcId);
00139         EV << "[DHT::handleRpcResponse()]\n"
00140            << "    DHT Put RPC Response received: id=" << rpcId
00141            << " msg=" << *_DHTPutResponse << " rtt=" << rtt
00142            << endl;
00143         break;
00144     }
00145     RPC_ON_RESPONSE(DHTGet) {
00146         handleGetResponse(_DHTGetResponse, rpcId);
00147         EV << "[DHT::handleRpcResponse()]\n"
00148            << "    DHT Get RPC Response received: id=" << rpcId
00149            << " msg=" << *_DHTGetResponse << " rtt=" << rtt
00150            << endl;
00151         break;
00152     }
00153     RPC_ON_RESPONSE(Lookup) {
00154         handleLookupResponse(_LookupResponse);
00155         EV << "[DHT::handleRpcResponse()]\n"
00156            << "    Replica Set RPC Response received: id=" << rpcId
00157            << " msg=" << *_LookupResponse << " rtt=" << rtt
00158            << endl;
00159         break;
00160     }
00161     RPC_SWITCH_END()
00162 }

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

This method is called if an RPC timeout has been reached.

Parameters:
msg The original RPC message.
dest The destination node
context Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code
rpcId The RPC id.
destKey the destination OverlayKey

Reimplemented from RpcListener.

Definition at line 164 of file DHT.cc.

00167 {
00168 
00169     RPC_SWITCH_START(msg)
00170     RPC_ON_CALL(DHTPut){
00171         EV << "[DHT::handleRpcResponse()]\n"
00172            << "    DHTPut Timeout"
00173            << endl;
00174 
00175         std::map<int, PutMapEntry>::iterator it2 =
00176                 putMap.find(rpcId);
00177 
00178         if (it2 == putMap.end()) //unknown request
00179             return;
00180 
00181         it2->second.numFailed++;
00182 
00183         if (it2->second.numFailed / (double)it2->second.numSent >= 0.5) {
00184             DHTputCAPIResponse* capiPutRespMsg = new DHTputCAPIResponse();
00185             capiPutRespMsg->setKey(_DHTPutCall->getKey());
00186             capiPutRespMsg->setIsSuccess(false);
00187             sendRpcResponse(it2->second.callMsg, capiPutRespMsg);
00188             //cout << "timeout 1" << endl;
00189             it2->second.callMsg = NULL;
00190             putMap.erase(rpcId);
00191         }
00192 
00193         break;
00194     }
00195     RPC_ON_CALL(DHTGet) {
00196         EV << "[DHT::handleRpcResponse()]\n"
00197            << "    DHTGet Timeout"
00198            << endl;
00199 
00200         std::map<unsigned int, BaseCallMessage*>::iterator it =
00201             rpcIdMap.find(_DHTGetCall->getNonce());
00202         std::map<int, GetMapEntry>::iterator it2 =
00203             getMap.find(rpcId);
00204 
00205         if (it2 == getMap.end()) { //unknown request
00206             return;
00207         }
00208 
00209         if (it != rpcIdMap.end()) {
00210             //we have sent a 'real' get request
00211             rpcIdMap.erase(_DHTGetCall->getNonce());
00212             //ask anyone else, if possible
00213 
00214             if ((it2->second.hashVector != NULL)
00215                 && (it2->second.hashVector->size()> 0)) {
00216 
00217                 DHTGetCall* getCall = new DHTGetCall();
00218                 getCall->setKey(_DHTGetCall->getKey());
00219                 getCall->setKind(_DHTGetCall->getKind());
00220                 getCall->setId(_DHTGetCall->getId());
00221                 getCall->setIsHash(false);
00222                 getCall->setBitLength(GETCALL_L(getCall));
00223                 RECORD_STATS(normalMessages++;
00224                              numBytesNormal += getCall->getByteLength());
00225 
00226                 int nonce = sendRouteRpcCall(TIER1_COMP,
00227                                              it2->second.hashVector->back(),
00228                                              getCall, NULL, DEFAULT_ROUTING,
00229                                              -1, 0, rpcId);
00230                 rpcIdMap.insert(make_pair(nonce, (BaseCallMessage*)NULL));
00231                 it2->second.hashVector->pop_back();
00232             } else {
00233                 // no one else
00234                 DHTgetCAPIResponse* capiGetRespMsg = new DHTgetCAPIResponse();
00235                 capiGetRespMsg->setIsSuccess(false);
00236                 sendRpcResponse(it2->second.callMsg,
00237                                 capiGetRespMsg);
00238                 //cout << "DHT: GET failed: no one else" << endl;
00239                 getMap.erase(rpcId);
00240                 return;
00241             }
00242 
00243         } else {
00244             //try to ask another one of the replica list for the hash
00245             if (it2->second.replica.size() > 0) {
00246                 DHTGetCall* getCall = new DHTGetCall();
00247                 getCall->setKey(_DHTGetCall->getKey());
00248                 getCall->setKind(_DHTGetCall->getKind());
00249                 getCall->setId(_DHTGetCall->getId());
00250                 getCall->setIsHash(true);
00251                 getCall->setBitLength(GETCALL_L(getCall));
00252 
00253                 RECORD_STATS(normalMessages++;
00254                              numBytesNormal += getCall->getByteLength());
00255 
00256                 sendRouteRpcCall(TIER1_COMP, it2->second.replica.back(),
00257                                  getCall, NULL, DEFAULT_ROUTING, -1, 0,
00258                                  rpcId);
00259                 it2->second.replica.pop_back();
00260             } else {
00261                 // no one else to ask, see what we can do with what we have
00262                 if (it2->second.numResponses > 0) {
00263                     unsigned int maxCount = 0;
00264                     ReplicaVector* hashVector = NULL;
00265                     std::map<BinaryValue, ReplicaVector>::iterator itHashes;
00266                     for (itHashes = it2->second.hashes.begin();
00267                          itHashes != it2->second.hashes.end(); itHashes++) {
00268 
00269                         if (itHashes->second.size()> maxCount) {
00270                             maxCount = itHashes->second.size();
00271                             hashVector = &(itHashes->second);
00272                         }
00273                     }
00274 
00275                     if ((double)maxCount/(double)it2->second.numResponses >=
00276                                                              ratioIdentical) {
00277                         it2->second.hashVector = hashVector;
00278                     }
00279                 }
00280 
00281                 if ((it2->second.hashVector != NULL)
00282                      && (it2->second.hashVector->size()> 0)) {
00283 
00284                     DHTGetCall* getCall = new DHTGetCall();
00285                     getCall->setKey(_DHTGetCall->getKey());
00286                     getCall->setKind(_DHTGetCall->getKind());
00287                     getCall->setId(_DHTGetCall->getId());
00288                     getCall->setIsHash(false);
00289                     getCall->setBitLength(GETCALL_L(getCall));
00290                     RECORD_STATS(normalMessages++;
00291                                  numBytesNormal += getCall->getByteLength());
00292                     int nonce = sendRouteRpcCall(TIER1_COMP,
00293                                                  it2->second.hashVector->back(),
00294                                                  getCall, NULL, DEFAULT_ROUTING,
00295                                                  -1, 0, rpcId);
00296                     rpcIdMap.insert(make_pair(nonce, (BaseCallMessage*)NULL));
00297                     it2->second.hashVector->pop_back();
00298                 } else {
00299                     DHTgetCAPIResponse* capiGetRespMsg = new DHTgetCAPIResponse();
00300                     capiGetRespMsg->setIsSuccess(false);
00301                     sendRpcResponse(it2->second.callMsg, capiGetRespMsg);
00302                     //cout << "DHT: GET failed: timeout (no one else)" << endl;
00303                     getMap.erase(rpcId);
00304                 }
00305             }
00306         }
00307         break;
00308     }
00309     RPC_SWITCH_END( )
00310 }

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

Reimplemented from BaseRpc.

Definition at line 101 of file DHT.cc.

00102 {
00103     DHTTtlTimer* msg_timer = dynamic_cast<DHTTtlTimer*> (msg);
00104 
00105     if (msg_timer) {
00106         EV << "[DHT::handleTimerEvent()]\n"
00107            << "    received timer ttl, key: "
00108            << msg_timer->getKey().toString(16)
00109            << "\n (overlay->getThisNode().getKey() = "
00110            << overlay->getThisNode().getKey().toString(16) << ")"
00111            << endl;
00112 
00113         dataStorage->removeData(msg_timer->getKey(), msg_timer->getKind(),
00114                                 msg_timer->getId());
00115     }
00116 }

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

initializes derived class-attributes

Parameters:
stage the init stage

Reimplemented from BaseApp.

Definition at line 73 of file DHT.cc.

00074 {
00075     if (stage != MIN_STAGE_APP)
00076         return;
00077 
00078     dataStorage = check_and_cast<DHTDataStorage*>
00079                       (getParentModule()->getSubmodule("dhtDataStorage"));
00080 
00081     numReplica = par("numReplica");
00082     numGetRequests = par("numGetRequests");
00083     ratioIdentical = par("ratioIdentical");
00084 
00085     if (numReplica > overlay->getMaxNumSiblings()) {
00086         opp_error("DHT::initialize(): numReplica bigger than what this "
00087                   "overlay can handle (%d)", overlay->getMaxNumSiblings());
00088     }
00089 
00090     maintenanceMessages = 0;
00091     normalMessages = 0;
00092     numBytesMaintenance = 0;
00093     numBytesNormal = 0;
00094     WATCH(maintenanceMessages);
00095     WATCH(normalMessages);
00096     WATCH(numBytesNormal);
00097     WATCH(numBytesMaintenance);
00098     WATCH_MAP(rpcIdMap);
00099 }

int DHT::resultValuesBitLength ( DHTGetResponse msg  )  [private]

Definition at line 847 of file DHT.cc.

00847                                                   {
00848     int bitSize = 0;
00849     for (uint i = 0; i < msg->getResultArraySize(); i++) {
00850         bitSize += msg->getResult(i).getValue().size();
00851 
00852     }
00853     return bitSize;
00854 }

void DHT::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 610 of file DHT.cc.

00611 {
00612     OverlayKey key;
00613     DHTPutCall* dhtMsg;
00614     bool err = false;
00615     DhtDataEntry entry;
00616     std::map<OverlayKey, DhtDataEntry>::iterator it = dataStorage->begin();
00617     for (unsigned int i = 0; i < dataStorage->getSize(); i++) {
00618         key = it->first;
00619         entry = it->second;
00620         if (joined) {
00621             if (entry.responsible && (overlay->isSiblingFor(node, key,
00622                                                             numReplica, &err)
00623                     || err)) { // hack for Chord, if we've got a new predecessor
00624 
00625                 dhtMsg = new DHTPutCall();
00626                 dhtMsg->setKey(key);
00627                 dhtMsg->setKind(entry.kind);
00628                 dhtMsg->setId(entry.id);
00629                 dhtMsg->setValue(entry.value);
00630                 dhtMsg->setTtl((int)SIMTIME_DBL(entry.ttlMessage->getArrivalTime()
00631                         - simTime()));
00632                 dhtMsg->setIsModifiable(entry.is_modifiable);
00633                 dhtMsg->setMaintenance(true);
00634                 dhtMsg->setBitLength(PUTCALL_L(dhtMsg));
00635                 RECORD_STATS(maintenanceMessages++;
00636                         numBytesMaintenance += dhtMsg->getByteLength());
00637                 sendRouteRpcCall(TIER1_COMP, node, dhtMsg);
00638             }
00639 
00640             if (err) {
00641                 EV << "[DHT::update()]\n"
00642                    << "    Unable to know if key: " << key
00643                    << " is in range of node: " << node
00644                    << endl;
00645             }
00646         } else {
00647 #if 0
00648             //the update concerns a node who has left
00649             //replicate
00650             LookupCall* replicaMsg = new LookupCall();
00651             replicaMsg->setKey(key);
00652             replicaMsg->setNumSiblings(numReplica);
00653             int nonce = sendInternalRpcCall(OVERLAY_COMP,
00654                                             replicaMsg);
00655             dhtMsg = new DHTPutCall();
00656             dhtMsg->setKey(key);
00657             dhtMsg->setValue(entry.value);
00658             dhtMsg->setTtl((int)(entry.ttlMessage->getArrivalTime()
00659                     - simTime()));
00660             dhtMsg->setIsModifiable(entry.is_modifiable);
00661             dhtMsg->setMaintenance(true);
00662             dhtMsg->setBitLength(PUTCALL_L(dhtMsg));
00663 
00664             rpcIdMap.insert(make_pair(nonce, dhtMsg));
00665 #endif
00666         }
00667 
00668         entry.responsible = overlay->isSiblingFor(overlay->getThisNode(),
00669                                                   key, 1, &err);
00670         it++;
00671     }
00672 }


Member Data Documentation

pointer to the dht data storage

Definition at line 105 of file DHT.h.

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

std::map<int, GetMapEntry> DHT::getMap [protected]

Definition at line 102 of file DHT.h.

Referenced by handleGetResponse(), handleLookupResponse(), handleRpcTimeout(), and ~DHT().

simtime_t DHT::lastGetCall [protected]

Definition at line 100 of file DHT.h.

Referenced by handleGetCAPIRequest().

double DHT::maintenanceMessages [protected]

Definition at line 96 of file DHT.h.

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

double DHT::normalMessages [protected]

double DHT::numBytesMaintenance [protected]

Definition at line 98 of file DHT.h.

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

double DHT::numBytesNormal [protected]

int DHT::numGetRequests [protected]

Definition at line 94 of file DHT.h.

Referenced by handleGetResponse(), handleLookupResponse(), and initializeApp().

int DHT::numReplica [protected]

Definition at line 93 of file DHT.h.

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

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

Definition at line 103 of file DHT.h.

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

double DHT::ratioIdentical [protected]

Definition at line 95 of file DHT.h.

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

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

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

Definition at line 101 of file DHT.h.

Referenced by handleGetCAPIRequest(), handleGetResponse(), handleLookupResponse(), handlePutCAPIRequest(), handleRpcTimeout(), initializeApp(), update(), and ~DHT().


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

Generated on Tue Sep 8 17:26:58 2009 for OverSim by  doxygen 1.5.8