#include <DHT.h>

Classes | |
| struct | GetMapEntry |
| struct | PutMapEntry |
Public Member Functions | |
| DHT () | |
| virtual | ~DHT () |
Protected Types | |
| typedef std::vector< NodeHandle > | ReplicaVector |
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, GetMapEntry > | getMap |
| std::map< int, PutMapEntry > | putMap |
| DHTDataStorage * | dataStorage |
| pointer to the dht data storage | |
Private Member Functions | |
| int | resultValuesBitLength (DHTGetResponse *msg) |
A Distributed Hash Table (DHT) for KBR protocols
Definition at line 44 of file DHT.h.
typedef std::vector<NodeHandle> DHT::ReplicaVector [protected] |
| DHT::DHT | ( | ) |
| 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 }
| 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.
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.
| 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.
| 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
| 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.
| 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 }
DHTDataStorage* DHT::dataStorage [protected] |
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] |
double DHT::maintenanceMessages [protected] |
Definition at line 96 of file DHT.h.
Referenced by finishApp(), handleLookupResponse(), initializeApp(), and update().
double DHT::normalMessages [protected] |
Definition at line 97 of file DHT.h.
Referenced by finishApp(), handleGetRequest(), handleGetResponse(), handleLookupResponse(), handlePutRequest(), handleRpcTimeout(), and initializeApp().
double DHT::numBytesMaintenance [protected] |
Definition at line 98 of file DHT.h.
Referenced by finishApp(), handleLookupResponse(), initializeApp(), and update().
double DHT::numBytesNormal [protected] |
Definition at line 99 of file DHT.h.
Referenced by finishApp(), handleGetRequest(), handleGetResponse(), handleLookupResponse(), handlePutRequest(), handleRpcTimeout(), and initializeApp().
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().
1.5.8