DHT.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2007 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 //
00018 
00024 #include <IPAddressResolver.h>
00025 
00026 #include "DHT.h"
00027 
00028 #include <RpcMacros.h>
00029 #include <BaseRpc.h>
00030 #include <GlobalStatistics.h>
00031 
00032 Define_Module(DHT);
00033 
00034 using namespace std;
00035 
00036 DHT::DHT()
00037 {
00038     dataStorage = NULL;
00039 }
00040 
00041 DHT::~DHT()
00042 {
00043     PendingRpcs::iterator it;
00044 
00045     for (it = pendingRpcs.begin(); it != pendingRpcs.end(); it++) {
00046         delete(it->second.putCallMsg);
00047         delete(it->second.getCallMsg);
00048     }
00049 
00050     pendingRpcs.clear();
00051 
00052     if (dataStorage != NULL) {
00053         dataStorage->clear();
00054     }
00055 }
00056 
00057 void DHT::initializeApp(int stage)
00058 {
00059     if (stage != MIN_STAGE_APP)
00060         return;
00061 
00062     dataStorage = check_and_cast<DHTDataStorage*>
00063                       (getParentModule()->getSubmodule("dhtDataStorage"));
00064 
00065     numReplica = par("numReplica");
00066     numGetRequests = par("numGetRequests");
00067     ratioIdentical = par("ratioIdentical");
00068     secureMaintenance = par("secureMaintenance");
00069     invalidDataAttack = par("invalidDataAttack");
00070     maintenanceAttack = par("maintenanceAttack");
00071 
00072     if ((int)numReplica > overlay->getMaxNumSiblings()) {
00073         opp_error("DHT::initialize(): numReplica bigger than what this "
00074                   "overlay can handle (%d)", overlay->getMaxNumSiblings());
00075     }
00076 
00077     maintenanceMessages = 0;
00078     normalMessages = 0;
00079     numBytesMaintenance = 0;
00080     numBytesNormal = 0;
00081     WATCH(maintenanceMessages);
00082     WATCH(normalMessages);
00083     WATCH(numBytesNormal);
00084     WATCH(numBytesMaintenance);
00085     WATCH_MAP(pendingRpcs);
00086 }
00087 
00088 void DHT::handleTimerEvent(cMessage* msg)
00089 {
00090     DHTTtlTimer* msg_timer = dynamic_cast<DHTTtlTimer*> (msg);
00091 
00092     if (msg_timer) {
00093         EV << "[DHT::handleTimerEvent()]\n"
00094            << "    received timer ttl, key: "
00095            << msg_timer->getKey().toString(16)
00096            << "\n (overlay->getThisNode().getKey() = "
00097            << overlay->getThisNode().getKey().toString(16) << ")"
00098            << endl;
00099 
00100         dataStorage->removeData(msg_timer->getKey(), msg_timer->getKind(),
00101                                 msg_timer->getId());
00102     }
00103 }
00104 
00105 bool DHT::handleRpcCall(BaseCallMessage* msg)
00106 {
00107     RPC_SWITCH_START(msg)
00108         // RPCs between nodes
00109         RPC_DELEGATE(DHTPut, handlePutRequest);
00110         RPC_DELEGATE(DHTGet, handleGetRequest);
00111         // internal RPCs
00112         RPC_DELEGATE(DHTputCAPI, handlePutCAPIRequest);
00113         RPC_DELEGATE(DHTgetCAPI, handleGetCAPIRequest);
00114         RPC_DELEGATE(DHTdump, handleDumpDhtRequest);
00115     RPC_SWITCH_END( )
00116 
00117     return RPC_HANDLED;
00118 }
00119 
00120 void DHT::handleRpcResponse(BaseResponseMessage* msg, cPolymorphic* context,
00121                             int rpcId, simtime_t rtt)
00122 {
00123     RPC_SWITCH_START(msg)
00124         RPC_ON_RESPONSE(DHTPut){
00125         handlePutResponse(_DHTPutResponse, rpcId);
00126         EV << "[DHT::handleRpcResponse()]\n"
00127            << "    DHT Put RPC Response received: id=" << rpcId
00128            << " msg=" << *_DHTPutResponse << " rtt=" << rtt
00129            << endl;
00130         break;
00131     }
00132     RPC_ON_RESPONSE(DHTGet) {
00133         handleGetResponse(_DHTGetResponse, rpcId);
00134         EV << "[DHT::handleRpcResponse()]\n"
00135            << "    DHT Get RPC Response received: id=" << rpcId
00136            << " msg=" << *_DHTGetResponse << " rtt=" << rtt
00137            << endl;
00138         break;
00139     }
00140     RPC_ON_RESPONSE(Lookup) {
00141         handleLookupResponse(_LookupResponse, rpcId);
00142         EV << "[DHT::handleRpcResponse()]\n"
00143            << "    Lookup RPC Response received: id=" << rpcId
00144            << " msg=" << *_LookupResponse << " rtt=" << rtt
00145            << endl;
00146         break;
00147     }
00148     RPC_SWITCH_END()
00149 }
00150 
00151 void DHT::handleRpcTimeout(BaseCallMessage* msg, const TransportAddress& dest,
00152                            cPolymorphic* context, int rpcId,
00153                            const OverlayKey& destKey)
00154 {
00155     RPC_SWITCH_START(msg)
00156     RPC_ON_CALL(DHTPut){
00157         EV << "[DHT::handleRpcResponse()]\n"
00158            << "    DHTPut Timeout"
00159            << endl;
00160 
00161         PendingRpcs::iterator it = pendingRpcs.find(rpcId);
00162 
00163         if (it == pendingRpcs.end()) // unknown request
00164             return;
00165 
00166         it->second.numFailed++;
00167 
00168         if (it->second.numFailed / (double)it->second.numSent >= 0.5) {
00169             DHTputCAPIResponse* capiPutRespMsg = new DHTputCAPIResponse();
00170             capiPutRespMsg->setIsSuccess(false);
00171             sendRpcResponse(it->second.putCallMsg, capiPutRespMsg);
00172             //cout << "timeout 1" << endl;
00173             pendingRpcs.erase(rpcId);
00174         }
00175 
00176         break;
00177     }
00178     RPC_ON_CALL(DHTGet) {
00179         EV << "[DHT::handleRpcResponse()]\n"
00180            << "    DHTGet Timeout"
00181            << endl;
00182 
00183         PendingRpcs::iterator it = pendingRpcs.find(rpcId);
00184 
00185         if (it == pendingRpcs.end()) { // unknown request
00186             return;
00187         }
00188 
00189         if (it->second.state == GET_VALUE_SENT) {
00190             // we have sent a 'real' get request
00191             // ask anyone else, if possible
00192             if ((it->second.hashVector != NULL)
00193                 && (it->second.hashVector->size() > 0)) {
00194 
00195                 DHTGetCall* getCall = new DHTGetCall();
00196                 getCall->setKey(_DHTGetCall->getKey());
00197                 getCall->setKind(_DHTGetCall->getKind());
00198                 getCall->setId(_DHTGetCall->getId());
00199                 getCall->setIsHash(false);
00200                 getCall->setBitLength(GETCALL_L(getCall));
00201                 RECORD_STATS(normalMessages++;
00202                              numBytesNormal += getCall->getByteLength());
00203 
00204                 sendRouteRpcCall(TIER1_COMP, it->second.hashVector->back(),
00205                                  getCall, NULL, DEFAULT_ROUTING, -1, 0, rpcId);
00206                 it->second.hashVector->pop_back();
00207             } else {
00208                 // no one else
00209                 DHTgetCAPIResponse* capiGetRespMsg = new DHTgetCAPIResponse();
00210                 capiGetRespMsg->setIsSuccess(false);
00211                 sendRpcResponse(it->second.getCallMsg,
00212                                 capiGetRespMsg);
00213                 //cout << "DHT: GET failed: timeout (no one else)" << endl;
00214                 pendingRpcs.erase(rpcId);
00215                 return;
00216             }
00217         } else {
00218             // timeout while waiting for hashes
00219             // try to ask another one of the replica list for the hash
00220             if (it->second.replica.size() > 0) {
00221                 DHTGetCall* getCall = new DHTGetCall();
00222                 getCall->setKey(_DHTGetCall->getKey());
00223                 getCall->setKind(_DHTGetCall->getKind());
00224                 getCall->setId(_DHTGetCall->getId());
00225                 getCall->setIsHash(true);
00226                 getCall->setBitLength(GETCALL_L(getCall));
00227 
00228                 RECORD_STATS(normalMessages++;
00229                              numBytesNormal += getCall->getByteLength());
00230 
00231                 sendRouteRpcCall(TIER1_COMP, it->second.replica.back(),
00232                                  getCall, NULL, DEFAULT_ROUTING, -1, 0,
00233                                  rpcId);
00234                 it->second.replica.pop_back();
00235             } else {
00236                 // no one else to ask, see what we can do with what we have
00237                 if (it->second.numResponses > 0) {
00238                     unsigned int maxCount = 0;
00239                     NodeVector* hashVector = NULL;
00240                     std::map<BinaryValue, NodeVector>::iterator itHashes;
00241                     for (itHashes = it->second.hashes.begin();
00242                          itHashes != it->second.hashes.end(); itHashes++) {
00243 
00244                         if (itHashes->second.size() > maxCount) {
00245                             maxCount = itHashes->second.size();
00246                             hashVector = &(itHashes->second);
00247                         }
00248                     }
00249 
00250                     // since it makes no difference for us, if we
00251                     // return a invalid result or return nothing,
00252                     // we simply return the value with the highest probability
00253                     it->second.hashVector = hashVector;
00254 #if 0
00255                     if ((double)maxCount/(double)it->second.numResponses >=
00256                                                              ratioIdentical) {
00257                         it->second.hashVector = hashVector;
00258                     }
00259 #endif
00260                 }
00261 
00262                 if ((it->second.hashVector != NULL)
00263                      && (it->second.hashVector->size() > 0)) {
00264 
00265                     DHTGetCall* getCall = new DHTGetCall();
00266                     getCall->setKey(_DHTGetCall->getKey());
00267                     getCall->setKind(_DHTGetCall->getKind());
00268                     getCall->setId(_DHTGetCall->getId());
00269                     getCall->setIsHash(false);
00270                     getCall->setBitLength(GETCALL_L(getCall));
00271                     RECORD_STATS(normalMessages++;
00272                                  numBytesNormal += getCall->getByteLength());
00273                     sendRouteRpcCall(TIER1_COMP, it->second.hashVector->back(),
00274                                      getCall, NULL, DEFAULT_ROUTING, -1,
00275                                      0, rpcId);
00276                     it->second.hashVector->pop_back();
00277                 } else {
00278                     // no more nodes to ask -> get failed
00279                     DHTgetCAPIResponse* capiGetRespMsg = new DHTgetCAPIResponse();
00280                     capiGetRespMsg->setIsSuccess(false);
00281                     sendRpcResponse(it->second.getCallMsg, capiGetRespMsg);
00282                     //cout << "DHT: GET failed: timeout2 (no one else)" << endl;
00283                     pendingRpcs.erase(rpcId);
00284                 }
00285             }
00286         }
00287         break;
00288     }
00289     RPC_SWITCH_END( )
00290 }
00291 
00292 void DHT::handlePutRequest(DHTPutCall* dhtMsg)
00293 {
00294     std::string tempString = "PUT_REQUEST received: "
00295             + std::string(dhtMsg->getKey().toString(16));
00296     getParentModule()->getParentModule()->bubble(tempString.c_str());
00297 
00298     bool err;
00299     bool isSibling = overlay->isSiblingFor(overlay->getThisNode(),
00300                   dhtMsg->getKey(), secureMaintenance ? numReplica : 1, &err);
00301     if (err) {
00302         isSibling = true;
00303     }
00304 
00305     if (secureMaintenance && dhtMsg->getMaintenance()) {
00306         DhtDataEntry* entry = dataStorage->getDataEntry(dhtMsg->getKey(),
00307                                                         dhtMsg->getKind(),
00308                                                         dhtMsg->getId());
00309         if (entry == NULL) {
00310             // add ttl timer
00311             DHTTtlTimer *timerMsg = new DHTTtlTimer("ttl_timer");
00312             timerMsg->setKey(dhtMsg->getKey());
00313             timerMsg->setKind(dhtMsg->getKind());
00314             timerMsg->setId(dhtMsg->getId());
00315             scheduleAt(simTime() + dhtMsg->getTtl(), timerMsg);
00316 
00317             entry = dataStorage->addData(dhtMsg->getKey(), dhtMsg->getKind(),
00318                                  dhtMsg->getId(), dhtMsg->getValue(), timerMsg,
00319                                  dhtMsg->getIsModifiable(), dhtMsg->getSrcNode(),
00320                                  isSibling);
00321         } else if ((entry->siblingVote.size() == 0) && isSibling) {
00322             // we already have a verified entry with this key and are
00323             // still responsible => ignore maintenance calls
00324             delete dhtMsg;
00325             return;
00326         }
00327 
00328         SiblingVoteMap::iterator it = entry->siblingVote.find(dhtMsg->getValue());
00329         if (it == entry->siblingVote.end()) {
00330             // new hash
00331             NodeVector vect;
00332             vect.add(dhtMsg->getSrcNode());
00333             entry->siblingVote.insert(make_pair(dhtMsg->getValue(),
00334                                                 vect));
00335         } else {
00336             it->second.add(dhtMsg->getSrcNode());
00337         }
00338 
00339         size_t maxCount = 0;
00340         SiblingVoteMap::iterator majorityIt;
00341 
00342         for (it = entry->siblingVote.begin(); it != entry->siblingVote.end(); it++) {
00343             if (it->second.size() > maxCount) {
00344                 maxCount = it->second.size();
00345                 majorityIt = it;
00346             }
00347         }
00348 
00349         entry->value = majorityIt->first;
00350         entry->responsible = true;
00351 
00352         if (maxCount > numReplica) {
00353             entry->siblingVote.clear();
00354         }
00355 
00356         // send back
00357         DHTPutResponse* responseMsg = new DHTPutResponse();
00358         responseMsg->setSuccess(true);
00359         responseMsg->setBitLength(PUTRESPONSE_L(responseMsg));
00360         RECORD_STATS(normalMessages++; numBytesNormal += responseMsg->getByteLength());
00361 
00362         sendRpcResponse(dhtMsg, responseMsg);
00363 
00364         return;
00365     }
00366 
00367 #if 0
00368     if (!(dataStorage->isModifiable(dhtMsg->getKey(), dhtMsg->getKind(),
00369                                     dhtMsg->getId()))) {
00370         // check if the put request came from the right node
00371         NodeHandle sourceNode = dataStorage->getSourceNode(dhtMsg->getKey(),
00372                                     dhtMsg->getKind(), dhtMsg->getId());
00373         if (((!sourceNode.isUnspecified())
00374                 && (!dhtMsg->getSrcNode().isUnspecified()) && (sourceNode
00375                 != dhtMsg->getSrcNode())) || ((dhtMsg->getMaintenance())
00376                 && (dhtMsg->getOwnerNode() == sourceNode))) {
00377             // TODO: set owner
00378             DHTPutResponse* responseMsg = new DHTPutResponse();
00379             responseMsg->setSuccess(false);
00380             responseMsg->setBitLength(PUTRESPONSE_L(responseMsg));
00381             RECORD_STATS(normalMessages++;
00382                          numBytesNormal += responseMsg->getByteLength());
00383             sendRpcResponse(dhtMsg, responseMsg);
00384             return;
00385         }
00386 
00387     }
00388 #endif
00389 
00390     // remove data item from local data storage
00391     dataStorage->removeData(dhtMsg->getKey(), dhtMsg->getKind(),
00392                             dhtMsg->getId());
00393 
00394     if (dhtMsg->getValue().size() > 0) {
00395         // add ttl timer
00396         DHTTtlTimer *timerMsg = new DHTTtlTimer("ttl_timer");
00397         timerMsg->setKey(dhtMsg->getKey());
00398         timerMsg->setKind(dhtMsg->getKind());
00399         timerMsg->setId(dhtMsg->getId());
00400         scheduleAt(simTime() + dhtMsg->getTtl(), timerMsg);
00401         // storage data item in local data storage
00402         dataStorage->addData(dhtMsg->getKey(), dhtMsg->getKind(),
00403                                      dhtMsg->getId(), dhtMsg->getValue(), timerMsg,
00404                              dhtMsg->getIsModifiable(), dhtMsg->getSrcNode(),
00405                              isSibling);
00406     }
00407 
00408     // send back
00409     DHTPutResponse* responseMsg = new DHTPutResponse();
00410     responseMsg->setSuccess(true);
00411     responseMsg->setBitLength(PUTRESPONSE_L(responseMsg));
00412     RECORD_STATS(normalMessages++; numBytesNormal += responseMsg->getByteLength());
00413 
00414     sendRpcResponse(dhtMsg, responseMsg);
00415 }
00416 
00417 void DHT::handleGetRequest(DHTGetCall* dhtMsg)
00418 {
00419     std::string tempString = "GET_REQUEST received: "
00420             + std::string(dhtMsg->getKey().toString(16));
00421 
00422     getParentModule()->getParentModule()->bubble(tempString.c_str());
00423 
00424     if (dhtMsg->getKey().isUnspecified()) {
00425         throw cRuntimeError("DHT::handleGetRequest: Unspecified key!");
00426     }
00427 
00428     DhtDumpVector* dataVect = dataStorage->dumpDht(dhtMsg->getKey(),
00429                                                    dhtMsg->getKind(),
00430                                                    dhtMsg->getId());
00431 
00432     if (overlay->isMalicious() && invalidDataAttack) {
00433         dataVect->resize(1);
00434         dataVect->at(0).setKey(dhtMsg->getKey());
00435         dataVect->at(0).setKind(dhtMsg->getKind());
00436         dataVect->at(0).setId(dhtMsg->getId());
00437         dataVect->at(0).setValue("Modified Data");
00438         dataVect->at(0).setTtl(3600*24*365);
00439         dataVect->at(0).setOwnerNode(overlay->getThisNode());
00440         dataVect->at(0).setIs_modifiable(false);
00441         dataVect->at(0).setResponsible(true);
00442     }
00443 
00444     // send back
00445     DHTGetResponse* responseMsg = new DHTGetResponse();
00446     responseMsg->setKey(dhtMsg->getKey());
00447     responseMsg->setIsHash(dhtMsg->getIsHash());
00448 
00449     if (dataVect->size() == 0) {
00450         responseMsg->setHashValue(BinaryValue::UNSPECIFIED_VALUE);
00451         responseMsg->setResultArraySize(0);
00452     } else {
00453         if (dhtMsg->getIsHash()) {
00454             // TODO: verify this
00455             BinaryValue resultValues;
00456             for (uint32_t i = 0; i < dataVect->size(); i++) {
00457                 resultValues += (*dataVect)[i].getValue();
00458             }
00459 
00460             CSHA1 sha1;
00461             BinaryValue hashValue(20);
00462             sha1.Reset();
00463             sha1.Update((uint8_t*) (&(*resultValues.begin())),
00464                         resultValues.size());
00465             sha1.Final();
00466             sha1.GetHash((unsigned char*)&hashValue[0]);
00467 
00468             responseMsg->setHashValue(hashValue);
00469         } else {
00470             responseMsg->setResultArraySize(dataVect->size());
00471 
00472             for (uint32_t i = 0; i < dataVect->size(); i++) {
00473                 responseMsg->setResult(i, (*dataVect)[i]);
00474             }
00475 
00476         }
00477     }
00478     delete dataVect;
00479 
00480     responseMsg->setBitLength(GETRESPONSE_L(responseMsg));
00481     RECORD_STATS(normalMessages++;
00482                  numBytesNormal += responseMsg->getByteLength());
00483     sendRpcResponse(dhtMsg, responseMsg);
00484 }
00485 
00486 void DHT::handlePutCAPIRequest(DHTputCAPICall* capiPutMsg)
00487 {
00488     // asks the replica list
00489     LookupCall* lookupCall = new LookupCall();
00490     lookupCall->setKey(capiPutMsg->getKey());
00491     lookupCall->setNumSiblings(numReplica);
00492     sendInternalRpcCall(OVERLAY_COMP, lookupCall, NULL, -1, 0,
00493                         capiPutMsg->getNonce());
00494 
00495     PendingRpcsEntry entry;
00496     entry.putCallMsg = capiPutMsg;
00497     entry.state = LOOKUP_STARTED;
00498     pendingRpcs.insert(make_pair(capiPutMsg->getNonce(), entry));
00499 }
00500 
00501 void DHT::handleGetCAPIRequest(DHTgetCAPICall* capiGetMsg)
00502 {
00503     LookupCall* lookupCall = new LookupCall();
00504     lookupCall->setKey(capiGetMsg->getKey());
00505     lookupCall->setNumSiblings(numReplica);
00506     sendInternalRpcCall(OVERLAY_COMP, lookupCall, NULL, -1, 0,
00507                         capiGetMsg->getNonce());
00508 
00509     PendingRpcsEntry entry;
00510     entry.getCallMsg = capiGetMsg;
00511     entry.state = LOOKUP_STARTED;
00512     pendingRpcs.insert(make_pair(capiGetMsg->getNonce(), entry));
00513 }
00514 
00515 void DHT::handleDumpDhtRequest(DHTdumpCall* call)
00516 {
00517     DHTdumpResponse* response = new DHTdumpResponse();
00518     DhtDumpVector* dumpVector = dataStorage->dumpDht();
00519 
00520     response->setRecordArraySize(dumpVector->size());
00521 
00522     for (uint32_t i = 0; i < dumpVector->size(); i++) {
00523         response->setRecord(i, (*dumpVector)[i]);
00524     }
00525 
00526     delete dumpVector;
00527 
00528     sendRpcResponse(call, response);
00529 }
00530 
00531 void DHT::handlePutResponse(DHTPutResponse* dhtMsg, int rpcId)
00532 {
00533     PendingRpcs::iterator it = pendingRpcs.find(rpcId);
00534 
00535     if (it == pendingRpcs.end()) // unknown request
00536         return;
00537 
00538     if (dhtMsg->getSuccess()) {
00539         it->second.numResponses++;
00540     } else {
00541         it->second.numFailed++;
00542     }
00543 
00544 
00545 //    if ((it->second.numFailed + it->second.numResponses) == it->second.numSent) {
00546     if (it->second.numResponses / (double)it->second.numSent > 0.5) {
00547 
00548         DHTputCAPIResponse* capiPutRespMsg = new DHTputCAPIResponse();
00549         capiPutRespMsg->setIsSuccess(true);
00550         sendRpcResponse(it->second.putCallMsg, capiPutRespMsg);
00551         pendingRpcs.erase(rpcId);
00552     }
00553 }
00554 
00555 void DHT::handleGetResponse(DHTGetResponse* dhtMsg, int rpcId)
00556 {
00557     NodeVector* hashVector = NULL;
00558     PendingRpcs::iterator it = pendingRpcs.find(rpcId);
00559 
00560     if (it == pendingRpcs.end()) // unknown request
00561         return;
00562 
00563     if (it->second.state == GET_VALUE_SENT) {
00564         // we have sent a 'real' get request
00565         if (!dhtMsg->getIsHash()) {
00566             // TODO verify hash
00567             DHTgetCAPIResponse* capiGetRespMsg = new DHTgetCAPIResponse();
00568             capiGetRespMsg->setResultArraySize(dhtMsg->getResultArraySize());
00569             for (uint i = 0; i < dhtMsg->getResultArraySize(); i++) {
00570                 capiGetRespMsg->setResult(i, dhtMsg->getResult(i));
00571             }
00572             capiGetRespMsg->setIsSuccess(true);
00573             sendRpcResponse(it->second.getCallMsg, capiGetRespMsg);
00574             pendingRpcs.erase(rpcId);
00575             return;
00576         }
00577     }
00578 
00579     if (dhtMsg->getIsHash()) {
00580         std::map<BinaryValue, NodeVector>::iterator itHashes =
00581             it->second.hashes.find(dhtMsg->getHashValue());
00582 
00583         if (itHashes == it->second.hashes.end()) {
00584             // new hash
00585             NodeVector vect;
00586             vect.push_back(dhtMsg->getSrcNode());
00587             it->second.hashes.insert(make_pair(dhtMsg->getHashValue(),
00588                                                vect));
00589         } else {
00590             itHashes->second.push_back(dhtMsg->getSrcNode());
00591         }
00592 
00593         it->second.numResponses++;
00594 
00595         if (it->second.state == GET_VALUE_SENT) {
00596             // we have already sent a real get request
00597             return;
00598         }
00599 
00600         // count the maximum number of equal hash values received so far
00601         unsigned int maxCount = 0;
00602 
00603 
00604         for (itHashes = it->second.hashes.begin();
00605         itHashes != it->second.hashes.end(); itHashes++) {
00606 
00607             if (itHashes->second.size() > maxCount) {
00608                 maxCount = itHashes->second.size();
00609                 hashVector = &(itHashes->second);
00610             }
00611         }
00612 
00613         if ((double) maxCount / (double) it->second.numAvailableReplica
00614                 >= ratioIdentical) {
00615             it->second.hashVector = hashVector;
00616         } else if (it->second.numResponses >= numGetRequests) {
00617             // we'll try to ask some other nodes
00618             if (it->second.replica.size() > 0) {
00619                 DHTGetCall* getCall = new DHTGetCall();
00620                 getCall->setKey(dhtMsg->getKey());
00621                 getCall->setKind(dhtMsg->getKind());
00622                 getCall->setId(dhtMsg->getId());
00623                 getCall->setIsHash(true);
00624                 getCall->setBitLength(GETCALL_L(getCall));
00625                 RECORD_STATS(normalMessages++;
00626                 numBytesNormal += getCall->getByteLength());
00627                 sendRouteRpcCall(TIER1_COMP,
00628                                  it->second.replica.back(), getCall,
00629                                  NULL, DEFAULT_ROUTING, -1, 0, rpcId);
00630                 it->second.replica.pop_back();
00631                 it->second.state = GET_HASH_SENT;
00632             } else if (hashVector == NULL) {
00633                 // we don't have anyone else to ask and no hash
00634                 DHTgetCAPIResponse* capiGetRespMsg =
00635                     new DHTgetCAPIResponse();
00636                 DhtDumpEntry result;
00637                 result.setKey(dhtMsg->getKey());
00638                 result.setValue(BinaryValue::UNSPECIFIED_VALUE);
00639                 capiGetRespMsg->setResultArraySize(1);
00640                 capiGetRespMsg->setResult(0, result);
00641                 capiGetRespMsg->setIsSuccess(false);
00642                 sendRpcResponse(it->second.getCallMsg, capiGetRespMsg);
00643 #if 0
00644                 cout << "DHT: GET failed: hash (no one else)" << endl;
00645                 cout << "numResponses: " << it->second.numResponses
00646                      << " numAvailableReplica: " << it->second.numAvailableReplica << endl;
00647 
00648                 for (itHashes = it->second.hashes.begin();
00649                      itHashes != it->second.hashes.end(); itHashes++) {
00650                     cout << "   - " << itHashes->first << " ("
00651                          << itHashes->second.size() << ")" << endl;
00652                 }
00653 #endif
00654 
00655                 pendingRpcs.erase(rpcId);
00656                 return;
00657             } else {
00658                 // we don't have anyone else to ask => take what we've got
00659                 it->second.hashVector = hashVector;
00660             }
00661         }
00662     }
00663 
00664     if ((it->second.state != GET_VALUE_SENT) &&
00665             (it->second.hashVector != NULL)) {
00666         // we have already received all the response and chosen a hash
00667         if (it->second.hashVector->size() > 0) {
00668             DHTGetCall* getCall = new DHTGetCall();
00669             getCall->setKey(it->second.getCallMsg->getKey());
00670             getCall->setKind(it->second.getCallMsg->getKind());
00671             getCall->setId(it->second.getCallMsg->getId());
00672             getCall->setIsHash(false);
00673             getCall->setBitLength(GETCALL_L(getCall));
00674             RECORD_STATS(normalMessages++;
00675                          numBytesNormal += getCall->getByteLength());
00676             sendRouteRpcCall(TIER1_COMP, it->second.hashVector->back(),
00677                              getCall, NULL, DEFAULT_ROUTING, -1, 0, rpcId);
00678             it->second.hashVector->pop_back();
00679             it->second.state = GET_VALUE_SENT;
00680         } else { // we don't have anyone else to ask
00681             DHTgetCAPIResponse* capiGetRespMsg = new DHTgetCAPIResponse();
00682             DhtDumpEntry result;
00683             result.setKey(dhtMsg->getKey());
00684             result.setValue(BinaryValue::UNSPECIFIED_VALUE);
00685             capiGetRespMsg->setResultArraySize(1);
00686             capiGetRespMsg->setResult(0, result);
00687             capiGetRespMsg->setIsSuccess(false);
00688             sendRpcResponse(it->second.getCallMsg, capiGetRespMsg);
00689             //cout << "DHT: GET failed: hash2 (no one else)" << endl;
00690             pendingRpcs.erase(rpcId);
00691         }
00692     }
00693 }
00694 
00695 void DHT::update(const NodeHandle& node, bool joined)
00696 {
00697     OverlayKey key;
00698     bool err = false;
00699     DhtDataEntry entry;
00700     std::map<OverlayKey, DhtDataEntry>::iterator it;
00701 
00702     EV << "[DHT::update() @ " << overlay->getThisNode().getAddress()
00703        << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00704        << "    Update called()"
00705        << endl;
00706 
00707     if (secureMaintenance) {
00708         for (it = dataStorage->begin(); it != dataStorage->end(); it++) {
00709             if (it->second.responsible) {
00710                 NodeVector* siblings = overlay->local_lookup(it->first,
00711                                                              numReplica,
00712                                                              false);
00713                 if (siblings->size() == 0) {
00714                     delete siblings;
00715                     continue;
00716                 }
00717 
00718                 if (joined) {
00719                     EV << "[DHT::update() @ " << overlay->getThisNode().getAddress()
00720                        << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00721                        << "    Potential new sibling for record " << it->first
00722                        << endl;
00723 
00724                     if (overlay->distance(node.getKey(), it->first) <=
00725                         overlay->distance(siblings->back().getKey(), it->first)) {
00726 
00727                         sendMaintenancePutCall(node, it->first, it->second);
00728                     }
00729 
00730                     if (overlay->distance(overlay->getThisNode().getKey(), it->first) >
00731                         overlay->distance(siblings->back().getKey(), it->first)) {
00732 
00733                         it->second.responsible = false;
00734                     }
00735                 } else {
00736                     if (overlay->distance(node.getKey(), it->first) <
00737                         overlay->distance(siblings->back().getKey(), it->first)) {
00738 
00739                         sendMaintenancePutCall(siblings->back(), it->first,
00740                                                it->second);
00741                     }
00742                 }
00743 
00744                 delete siblings;
00745             }
00746         }
00747 
00748         return;
00749     }
00750 
00751     for (it = dataStorage->begin(); it != dataStorage->end(); it++) {
00752         key = it->first;
00753         entry = it->second;
00754         if (joined) {
00755             if (entry.responsible && (overlay->isSiblingFor(node, key,
00756                                                             numReplica, &err)
00757                     || err)) { // hack for Chord, if we've got a new predecessor
00758 
00759                 if (err) {
00760                     EV << "[DHT::update()]\n"
00761                        << "    Unable to know if key: " << key
00762                        << " is in range of node: " << node
00763                        << endl;
00764                     // For Chord: we've got a new predecessor
00765                     // TODO: only send record, if we are not responsible any more
00766                     // TODO: check all protocols to change routing table first,
00767                     //       and than call update.
00768 
00769                     //if (overlay->isSiblingFor(overlay->getThisNode(), key, 1, &err)) {
00770                     //    continue;
00771                     //}
00772                 }
00773 
00774                 sendMaintenancePutCall(node, key, entry);
00775             }
00776         }
00777         //TODO: move this to the inner block above?
00778         entry.responsible = overlay->isSiblingFor(overlay->getThisNode(),
00779                                                   key, 1, &err);
00780     }
00781 }
00782 
00783 void DHT::sendMaintenancePutCall(const TransportAddress& node,
00784                                  const OverlayKey& key,
00785                                  const DhtDataEntry& entry) {
00786 
00787     DHTPutCall* dhtMsg = new DHTPutCall();
00788 
00789     dhtMsg->setKey(key);
00790     dhtMsg->setKind(entry.kind);
00791     dhtMsg->setId(entry.id);
00792 
00793     if (overlay->isMalicious() && maintenanceAttack) {
00794         dhtMsg->setValue("Modified Data");
00795     } else {
00796         dhtMsg->setValue(entry.value);
00797     }
00798 
00799     dhtMsg->setTtl((int)SIMTIME_DBL(entry.ttlMessage->getArrivalTime()
00800                                     - simTime()));
00801     dhtMsg->setIsModifiable(entry.is_modifiable);
00802     dhtMsg->setMaintenance(true);
00803     dhtMsg->setBitLength(PUTCALL_L(dhtMsg));
00804     RECORD_STATS(maintenanceMessages++;
00805                  numBytesMaintenance += dhtMsg->getByteLength());
00806 
00807     sendRouteRpcCall(TIER1_COMP, node, dhtMsg);
00808 }
00809 
00810 void DHT::handleLookupResponse(LookupResponse* lookupMsg, int rpcId)
00811 {
00812     PendingRpcs::iterator it = pendingRpcs.find(rpcId);
00813 
00814     if (it == pendingRpcs.end()) {
00815         return;
00816     }
00817 
00818     if (it->second.putCallMsg != NULL) {
00819 
00820 #if 0
00821         cout << "DHT::handleLookupResponse(): PUT "
00822              << lookupMsg->getKey() << " ("
00823              << overlay->getThisNode().getKey() << ")" << endl;
00824 
00825         for (unsigned int i = 0; i < lookupMsg->getSiblingsArraySize(); i++) {
00826             cout << i << ": " << lookupMsg->getSiblings(i) << endl;
00827         }
00828 #endif
00829 
00830         if ((lookupMsg->getIsValid() == false)
00831                 || (lookupMsg->getSiblingsArraySize() == 0)) {
00832 
00833             EV << "[DHT::handleLookupResponse()]\n"
00834                << "    Unable to get replica list : invalid lookup"
00835                << endl;
00836             DHTputCAPIResponse* capiPutRespMsg = new DHTputCAPIResponse();
00837             capiPutRespMsg->setIsSuccess(false);
00838             //cout << "DHT::lookup failed" << endl;
00839             sendRpcResponse(it->second.putCallMsg, capiPutRespMsg);
00840             pendingRpcs.erase(rpcId);
00841             return;
00842         }
00843 
00844         if ((it->second.putCallMsg->getId() == 0) &&
00845                 (it->second.putCallMsg->getValue().size() > 0)) {
00846             // pick a random id before replication of the data item
00847             // id 0 is kept for delete requests (i.e. a put with empty value)
00848             it->second.putCallMsg->setId(intuniform(1, 2147483647));
00849         }
00850 
00851         for (unsigned int i = 0; i < lookupMsg->getSiblingsArraySize(); i++) {
00852             DHTPutCall* dhtMsg = new DHTPutCall();
00853             dhtMsg->setKey(it->second.putCallMsg->getKey());
00854             dhtMsg->setKind(it->second.putCallMsg->getKind());
00855             dhtMsg->setId(it->second.putCallMsg->getId());
00856             dhtMsg->setValue(it->second.putCallMsg->getValue());
00857             dhtMsg->setTtl(it->second.putCallMsg->getTtl());
00858             dhtMsg->setIsModifiable(it->second.putCallMsg->getIsModifiable());
00859             dhtMsg->setMaintenance(false);
00860             dhtMsg->setBitLength(PUTCALL_L(dhtMsg));
00861             RECORD_STATS(normalMessages++;
00862                          numBytesNormal += dhtMsg->getByteLength());
00863             sendRouteRpcCall(TIER1_COMP, lookupMsg->getSiblings(i),
00864                              dhtMsg, NULL, DEFAULT_ROUTING, -1,
00865                              0, rpcId);
00866         }
00867 
00868         it->second.state = PUT_SENT;
00869         it->second.numResponses = 0;
00870         it->second.numFailed = 0;
00871         it->second.numSent = lookupMsg->getSiblingsArraySize();
00872     }
00873     else if (it->second.getCallMsg != NULL) {
00874 
00875 #if 0
00876         cout << "DHT::handleLookupResponse(): GET "
00877              << lookupMsg->getKey() << " ("
00878              << overlay->getThisNode().getKey() << ")" << endl;
00879 
00880         for (unsigned int i = 0; i < lookupMsg->getSiblingsArraySize(); i++) {
00881             cout << i << ": " << lookupMsg->getSiblings(i) << endl;
00882         }
00883 #endif
00884 
00885         if ((lookupMsg->getIsValid() == false)
00886                 || (lookupMsg->getSiblingsArraySize() == 0)) {
00887 
00888             EV << "[DHT::handleLookupResponse()]\n"
00889                << "    Unable to get replica list : invalid lookup"
00890                << endl;
00891             DHTgetCAPIResponse* capiGetRespMsg = new DHTgetCAPIResponse();
00892             DhtDumpEntry result;
00893             result.setKey(lookupMsg->getKey());
00894             result.setValue(BinaryValue::UNSPECIFIED_VALUE);
00895             capiGetRespMsg->setResultArraySize(1);
00896             capiGetRespMsg->setResult(0, result);
00897             capiGetRespMsg->setIsSuccess(false);
00898             //cout << "DHT: lookup failed 2" << endl;
00899             sendRpcResponse(it->second.getCallMsg, capiGetRespMsg);
00900             pendingRpcs.erase(rpcId);
00901             return;
00902         }
00903 
00904         it->second.numSent = 0;
00905 
00906         for (unsigned int i = 0; i < lookupMsg->getSiblingsArraySize(); i++) {
00907             if (i < (unsigned int)numGetRequests) {
00908                 DHTGetCall* dhtMsg = new DHTGetCall();
00909                 dhtMsg->setKey(it->second.getCallMsg->getKey());
00910                 dhtMsg->setKind(it->second.getCallMsg->getKind());
00911                 dhtMsg->setId(it->second.getCallMsg->getId());
00912                 dhtMsg->setIsHash(true);
00913                 dhtMsg->setBitLength(GETCALL_L(dhtMsg));
00914                 RECORD_STATS(normalMessages++;
00915                              numBytesNormal += dhtMsg->getByteLength());
00916                 sendRouteRpcCall(TIER1_COMP, lookupMsg->getSiblings(i), dhtMsg,
00917                                  NULL, DEFAULT_ROUTING, -1, 0, rpcId);
00918                 it->second.numSent++;
00919             } else {
00920                 // we don't send, we just store the remaining keys
00921                 it->second.replica.push_back(lookupMsg->getSiblings(i));
00922             }
00923         }
00924 
00925         it->second.numAvailableReplica = lookupMsg->getSiblingsArraySize();
00926         it->second.numResponses = 0;
00927         it->second.hashVector = NULL;
00928         it->second.state = GET_HASH_SENT;
00929     }
00930 }
00931 
00932 void DHT::finishApp()
00933 {
00934     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00935 
00936     if (time >= GlobalStatistics::MIN_MEASURED) {
00937         globalStatistics->addStdDev("DHT: Sent Maintenance Messages/s",
00938                                     maintenanceMessages / time);
00939         globalStatistics->addStdDev("DHT: Sent Normal Messages/s",
00940                                     normalMessages / time);
00941         globalStatistics->addStdDev("DHT: Sent Maintenance Bytes/s",
00942                                     numBytesMaintenance / time);
00943         globalStatistics->addStdDev("DHT: Sent Normal Bytes/s",
00944                                     numBytesNormal / time);
00945     }
00946 }
00947 
00948 int DHT::resultValuesBitLength(DHTGetResponse* msg) {
00949     int bitSize = 0;
00950     for (uint i = 0; i < msg->getResultArraySize(); i++) {
00951         bitSize += msg->getResult(i).getValue().size();
00952 
00953     }
00954     return bitSize;
00955 }
00956 
00957 std::ostream& operator<<(std::ostream& os, const DHT::PendingRpcsEntry& entry)
00958 {
00959     if (entry.getCallMsg) {
00960         os << "GET";
00961     } else if (entry.putCallMsg) {
00962         os << "PUT";
00963     }
00964 
00965     os << " state: " << entry.state
00966        << " numSent: " << entry.numSent
00967        << " numResponses: " << entry.numResponses
00968        << " numFailed: " << entry.numFailed
00969        << " numAvailableReplica: " << entry.numAvailableReplica;
00970 
00971     if (entry.replica.size() > 0) {
00972         os << " replicaSize: " << entry.replica.size();
00973     }
00974 
00975     if (entry.hashVector != NULL) {
00976         os << " hashVectorSize: " << entry.hashVector->size();
00977     }
00978 
00979     if (entry.hashes.size() > 0) {
00980         os << " hashes:";
00981         std::map<BinaryValue, NodeVector>::const_iterator it;
00982 
00983         int i = 0;
00984         for (it = entry.hashes.begin(); it != entry.hashes.end(); it++, i++) {
00985             os << " hash" << i << ":" << it->second.size();
00986         }
00987     }
00988 
00989     return os;
00990 }
Generated on Wed May 26 16:21:14 2010 for OverSim by  doxygen 1.6.3