PastryLeafSet.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 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 "PastryLeafSet.h"
00025 #include "PastryTypes.h"
00026 #include "NodeVector.h"
00027 
00028 #if 0
00029 #define LEAF_TEST() \
00030     do {\
00031         uint32_t count = 0;\
00032         uint32_t i = 0, j = leaves.size() - 1;\
00033         while (leaves[i].isUnspecified() && i < j) ++i;\
00034         while (leaves[j].isUnspecified() && i < j) --j;\
00035         if (i == j) break;\
00036         if (!owner.getKey().isBetween(leaves[(leaves.size() / 2) - 1].getKey(),\
00037                                  leaves[leaves.size() / 2].getKey()))\
00038                 ASSERT2(false, "leafset broken!");\
00039         for (uint32_t ci = i + 1; ci < j; ++ci) {\
00040             if (leaves[ci - 1].getKey() >= leaves[ci].getKey()) {\
00041                 count++;\
00042             }\
00043         }\
00044         if (leaves[j].getKey() >= leaves[i].getKey()) count++;\
00045         ASSERT2(count <= 1, "leafset broken!");\
00046     } while (false);
00047 #else
00048 #define LEAF_TEST() {}
00049 #endif
00050 
00051 Define_Module(PastryLeafSet);
00052 
00053 void PastryLeafSet::earlyInit(void)
00054 {
00055     WATCH_VECTOR(leaves);
00056 }
00057 
00058 void PastryLeafSet::initializeSet(uint32_t numberOfLeaves,
00059                                   uint32_t bitsPerDigit,
00060                                   simtime_t repairTimeout,
00061                                   const NodeHandle& owner,
00062                                   BasePastry *overlay)
00063 {
00064     if (numberOfLeaves % 2) throw "numberOfLeaves must be even.";
00065 
00066     this->owner = owner;
00067     this->numberOfLeaves = numberOfLeaves;
00068     this->repairTimeout = repairTimeout;
00069     this->bitsPerDigit = bitsPerDigit;
00070     this->overlay = overlay;
00071 
00072     if (!leaves.empty()) leaves.clear();
00073 
00074     // fill Set with unspecified node handles
00075     for (uint32_t i = numberOfLeaves; i>0; i--)
00076         leaves.push_back(NodeHandle::UNSPECIFIED_NODE);
00077 
00078     // initialize iterators to mark the beginning of bigger/smaller keys
00079     // in the set
00080     bigger = leaves.begin() + (numberOfLeaves >> 1);
00081     smaller = bigger - 1;
00082 
00083     // reset repair marker:
00084     if (!awaitingRepair.empty()) awaitingRepair.clear();
00085 
00086     newLeafs = false;
00087     isFull = false;
00088     wasFull = false;
00089 }
00090 
00091 const NodeHandle& PastryLeafSet::getSuccessor(void) const
00092 {
00093     return *bigger;
00094 }
00095 
00096 const NodeHandle& PastryLeafSet::getPredecessor(void) const
00097 {
00098     return *smaller;
00099 }
00100 
00101 bool PastryLeafSet::isValid(void) const
00102 {
00103     return (!(smaller->isUnspecified() || bigger->isUnspecified()));
00104 }
00105 
00106 const NodeHandle& PastryLeafSet::getDestinationNode(
00107     const OverlayKey& destination)
00108 {
00109     std::vector<NodeHandle>::const_iterator i;
00110     const OverlayKey* smallest;
00111     const OverlayKey* biggest;
00112     const NodeHandle* ret = &NodeHandle::UNSPECIFIED_NODE;
00113 
00114     // check whether destination is inside leafSet:
00115 
00116     smallest = &(getSmallestKey());
00117     biggest = &(getBiggestKey());
00118     if (smallest->isUnspecified()) smallest = &(owner.getKey());
00119     if (biggest->isUnspecified()) biggest = &(owner.getKey());
00120 
00121     if (!destination.isBetweenLR(*smallest, *biggest)) return *ret;
00122 
00123     // find the closest node:
00124 
00125     for (i = leaves.begin(); i != leaves.end(); i++) {
00126         if (i->isUnspecified()) continue;
00127 
00128         // note for next line:
00129         // * dereferences iterator, & gets address of element.
00130         if (isCloser(*i, destination, *ret)) ret = &(*i);
00131     }
00132 
00133     return *ret;
00134 }
00135 
00136 bool PastryLeafSet::isClosestNode(const OverlayKey& destination) const
00137 {
00138     // check for simple cases first
00139     if (owner.getKey() == destination) {
00140         return true;
00141     }
00142 
00143     if (bigger->isUnspecified() && smaller->isUnspecified()) {
00144         return true;
00145     }
00146 
00147     // check if the next bigger or smaller node in the set is closer
00148     // than own node
00149     bool biggerIsCloser = false;
00150     bool smallerIsCloser = false;
00151 
00152     if (! bigger->isUnspecified()) {
00153         biggerIsCloser = isCloser(*bigger, destination);
00154     }
00155     if (! smaller->isUnspecified()) {
00156         smallerIsCloser = isCloser(*smaller, destination);
00157     }
00158 
00159     // return true if both are not closer
00160     return ((!biggerIsCloser) && (!smallerIsCloser));
00161 }
00162 
00163 void PastryLeafSet::dumpToStateMessage(PastryStateMessage* msg) const
00164 {
00165     uint32_t i = 0;
00166     uint32_t size = 0;
00167     std::vector<NodeHandle>::const_iterator it;
00168 
00169     msg->setLeafSetArraySize(numberOfLeaves);
00170     for (it = leaves.begin(); it != leaves.end(); it++) {
00171         if (!it->isUnspecified()) {
00172             ++size;
00173             msg->setLeafSet(i++, *it);
00174         }
00175     }
00176     msg->setLeafSetArraySize(size);
00177 }
00178 
00179 //TODO ugly duplication of code
00180 void PastryLeafSet::dumpToStateMessage(PastryLeafsetMessage* msg) const
00181 {
00182     uint32_t i = 0;
00183     uint32_t size = 0;
00184     std::vector<NodeHandle>::const_iterator it;
00185 
00186     msg->setLeafSetArraySize(numberOfLeaves);
00187     for (it = leaves.begin(); it != leaves.end(); it++) {
00188         if (!it->isUnspecified()) {
00189             ++size;
00190             msg->setLeafSet(i++, *it);
00191         }
00192     }
00193     msg->setLeafSetArraySize(size);
00194 }
00195 
00196 const TransportAddress& PastryLeafSet::getRandomNode()
00197 {
00198     //std::vector<NodeHandle>::iterator i;
00199     uint32_t rnd;
00200     int i;
00201 
00202     rnd = intuniform(0, numberOfLeaves - 1, 0);
00203     i = rnd;
00204     //while (rnd < leaves.size()) {
00205     while (i < (int)leaves.size()) {
00206         if (!leaves[i].isUnspecified()) return leaves[i];
00207         else i++;//rnd++;
00208     }
00209     i = rnd;
00210     while (i >= 0) {
00211         if (!leaves[i].isUnspecified()) return leaves[i];
00212         else i--;
00213     }
00214     EV << "Leafset::getRandomNode() returns UNSPECIFIED_NODE"
00215           "Leafset empty??" << endl;
00216     return TransportAddress::UNSPECIFIED_NODE;
00217 
00218 }
00219 
00220 NodeVector* PastryLeafSet::createSiblingVector(const OverlayKey& key,
00221         int numSiblings) const
00222 {
00223     std::vector<NodeHandle>::const_iterator it;
00224 
00225     // create temporary comparator
00226     KeyDistanceComparator<KeyRingMetric>* comp =
00227         new KeyDistanceComparator<KeyRingMetric>( key );
00228 
00229     // create result vector
00230     NodeVector* result = new NodeVector( numSiblings, comp );
00231 
00232     result->add(owner);
00233 
00234     for (it = leaves.begin(); it != leaves.end(); it++) {
00235         if (!it->isUnspecified()) {
00236             result->add(*it);
00237         }
00238     }
00239 
00240     delete comp;
00241 
00242     if (!isValid()) {
00243         return result;
00244     }
00245 
00246     // if the leafset is not full, we could have a very small network
00247     // => return true (FIXME hack)
00248     if (leaves.front().isUnspecified() || leaves.back().isUnspecified()) {
00249         return result;
00250     }
00251 
00252     if ((result->contains(getBiggestKey())) ||
00253         (result->contains(getSmallestKey()))) {
00254         delete result;
00255         return NULL;
00256     }
00257 
00258     return result;
00259 }
00260 
00261 bool PastryLeafSet::mergeNode(const NodeHandle& node, simtime_t prox)
00262 {
00263     assert(node != overlay->getThisNode());
00264 
00265     std::vector<NodeHandle>::iterator it, it_left, it_right;
00266     const OverlayKey* last_left = &(owner.getKey());
00267     const OverlayKey* last_right = &(owner.getKey());
00268 
00269     it_left = smaller;
00270     it_right = bigger;
00271 
00272     // avoid duplicates
00273     for (it = leaves.begin(); it != leaves.end(); ++it) {
00274         if (it->isUnspecified()) {
00275             isFull = false;
00276             continue;
00277         }
00278         if (it->getKey() == node.getKey()) return false;
00279     }
00280 
00281     // look for correct position in left and right half of leafset
00282     while (true) {
00283         if(!isFull) {
00284             // both sides free
00285             if(it_left->getKey().isUnspecified() &&
00286                it_right->getKey().isUnspecified()) {
00287                 insertLeaf(it_left, node);
00288                 return true;
00289             }
00290             if (it_left->getKey().isUnspecified() &&
00291                 !node.getKey().isBetween(*last_right, it_right->getKey())) {
00292                 // end of smaller entries found
00293                 insertLeaf(it_left, node);
00294                 return true;
00295             }
00296             if (it_right->getKey().isUnspecified() &&
00297                 !node.getKey().isBetween(it_left->getKey(), *last_left)) {
00298                 // end of bigger entries found
00299                 insertLeaf(it_right, node);
00300                 return true;
00301             }
00302         }
00303         // left side
00304         if (node.getKey().isBetween(it_left->getKey(), *last_left)) {
00305             // found correct position for inserting the new entry between
00306             // existing ones
00307             insertLeaf(it_left, node);
00308             return true;
00309         }
00310         // right side
00311         if (node.getKey().isBetween(*last_right, it_right->getKey())) {
00312             // found correct position for inserting the new entry between
00313             // existing ones
00314             insertLeaf(it_right, node);
00315             return true;
00316         }
00317 
00318         last_right = &(it_right->getKey());
00319         ++it_right;
00320 
00321         if (it_right == leaves.end()) break;
00322 
00323         last_left = &(it_left->getKey());
00324         --it_left;
00325     }
00326     return false;
00327 }
00328 
00329 void PastryLeafSet::insertLeaf(std::vector<NodeHandle>::iterator& it,
00330                                const NodeHandle& node)
00331 {
00332     assert(node != overlay->getThisNode());
00333 
00334     LEAF_TEST();
00335     bool issmaller = (it <= smaller);
00336     if (issmaller) {
00337         if (!leaves.front().isUnspecified())  {
00338             overlay->callUpdate(leaves.front(), false);
00339         }
00340         overlay->callUpdate(node, true);
00341 
00342         leaves.insert(++it, node);
00343         NodeHandle& temp = leaves.front();
00344         if (!temp.isUnspecified() && leaves.back().isUnspecified()) {
00345             leaves.back() = temp;
00346         }
00347         leaves.erase(leaves.begin());
00348 
00349 
00350     } else {
00351         if (!leaves.back().isUnspecified())  {
00352             overlay->callUpdate(leaves.back(), false);
00353         }
00354         overlay->callUpdate(node, true);
00355 
00356         leaves.insert(it, node);
00357         NodeHandle& temp = leaves.back();
00358         if (!temp.isUnspecified() && leaves.front().isUnspecified()) {
00359             leaves.front() = temp;
00360         }
00361         leaves.pop_back();
00362     }
00363 
00364     if (!leaves.front().isUnspecified() &&
00365         !leaves.back().isUnspecified()) {
00366         isFull = true;
00367     } else isFull = false;
00368 
00369     newLeafs = true;
00370     bigger = leaves.begin() + (numberOfLeaves >> 1);
00371     smaller = bigger - 1;
00372 
00373     // ensure balance in leafset
00374     if (!isFull) {
00375         balanceLeafSet();
00376     }
00377     LEAF_TEST();
00378 }
00379 
00380 bool PastryLeafSet::balanceLeafSet()
00381 {
00382     if (isFull ||
00383         (!leaves.front().isUnspecified() &&
00384          !(leaves.end() - 2)->isUnspecified()) ||
00385         (!leaves.back().isUnspecified() &&
00386          !(leaves.begin() + 1)->isUnspecified()))
00387         return false;
00388 
00389     std::vector<NodeHandle>::iterator it_left, it_right;
00390 
00391     for (it_left = smaller, it_right = bigger;
00392          it_right != leaves.end(); --it_left, ++it_right) {
00393         if (it_left->isUnspecified()) {
00394             if (it_right->isUnspecified() ||
00395                 (it_right + 1) == leaves.end() ||
00396                 (it_right + 1)->isUnspecified()) return false;
00397             *it_left = *(it_right + 1);
00398             *(it_right + 1) = NodeHandle::UNSPECIFIED_NODE;
00399             return true;
00400         } else if (it_right->isUnspecified()) {
00401 
00402             if (it_left == leaves.begin() ||
00403                 (it_left - 1)->isUnspecified()) return false;
00404             *it_right = *(it_left - 1);
00405             *(it_left - 1) = NodeHandle::UNSPECIFIED_NODE;
00406             return true;
00407         }
00408     }
00409     return false; // should not happen
00410 }
00411 
00412 void PastryLeafSet::dumpToVector(std::vector<TransportAddress>& affected) const
00413 {
00414     std::vector<NodeHandle>::const_iterator it;
00415 
00416     for (it = leaves.begin(); it != leaves.end(); it++)
00417         if (!it->isUnspecified())
00418             affected.push_back(*it);
00419 }
00420 
00421 const NodeHandle& PastryLeafSet::getSmallestNode(void) const
00422 {
00423     std::vector<NodeHandle>::const_iterator i = leaves.begin();
00424     while ((i->isUnspecified()) && (i != smaller)) i++;
00425     assert(i->isUnspecified() || *i != overlay->getThisNode());
00426     return *i;
00427 }
00428 
00429 const OverlayKey& PastryLeafSet::getSmallestKey(void) const
00430 {
00431     return getSmallestNode().getKey();
00432 }
00433 
00434 const NodeHandle& PastryLeafSet::getBiggestNode(void) const
00435 {
00436     std::vector<NodeHandle>::const_iterator i = leaves.end()-1;
00437     while ((i->isUnspecified()) && (i != bigger)) i--;
00438     assert(i->isUnspecified() || *i != overlay->getThisNode());
00439     return *i;
00440 }
00441 
00442 const OverlayKey& PastryLeafSet::getBiggestKey(void) const
00443 {
00444     return getBiggestNode().getKey();
00445 }
00446 
00447 void PastryLeafSet::findCloserNodes(const OverlayKey& destination,
00448                                     NodeVector* nodes)
00449 {
00450     std::vector<NodeHandle>::const_iterator it;
00451 
00452     for (it = leaves.begin(); it != leaves.end(); it++)
00453         if (!it->isUnspecified())
00454             nodes->add(*it);
00455 
00456 }
00457 
00458 const NodeHandle& PastryLeafSet::findCloserNode(const OverlayKey& destination,
00459                                                 bool optimize)
00460 {
00461     std::vector<NodeHandle>::const_iterator i;
00462     const NodeHandle* ret = &NodeHandle::UNSPECIFIED_NODE;
00463 
00464     // this will only be called after getDestinationNode() returned
00465     // NodeHandle::UNSPECIFIED_NODE, so a closer Node can only be the biggest
00466     // or the smallest node in the LeafSet.
00467 
00468     const NodeHandle& smallest = getSmallestNode();
00469     const NodeHandle& biggest = getBiggestNode();
00470 
00471     if ((!smallest.isUnspecified()) &&
00472             (specialCloserCondition(smallest, destination, *ret))) {
00473         if (optimize) ret = &smallest;
00474         else return smallest;
00475     }
00476 
00477     if ((!biggest.isUnspecified()) &&
00478             (specialCloserCondition(biggest, destination, *ret))) {
00479         if (optimize) ret = &biggest;
00480         else return biggest;
00481     }
00482 
00483     return *ret;
00484 }
00485 
00486 const TransportAddress& PastryLeafSet::failedNode(const TransportAddress& failed)
00487 {
00488     std::vector<NodeHandle>::iterator i;
00489     const TransportAddress* ask;
00490     bool left = true;
00491 
00492     // search failed node in leafset:
00493     for (i = leaves.begin(); i != leaves.end(); i++) {
00494         if (i == bigger) left = false;
00495         if ((! i->isUnspecified()) && (i->getAddress() == failed.getAddress())) break;
00496     }
00497 
00498     // failed node not in leafset:
00499     if (i == leaves.end()) return TransportAddress::UNSPECIFIED_NODE;
00500 
00501     overlay->callUpdate(*i, false);
00502 
00503     // remove failed node:
00504     leaves.erase(i);
00505     newLeafs = true;
00506 
00507     wasFull = isFull;
00508     isFull = false;
00509 
00510     // insert UNSPECIFIED_NODE at front or back and return correct node
00511     // to ask for repair:
00512     if (left) {
00513         leaves.insert(leaves.begin(), NodeHandle::UNSPECIFIED_NODE);
00514         bigger = leaves.begin() + (numberOfLeaves >> 1);
00515         smaller = bigger - 1;
00516         ask = static_cast<const TransportAddress*>(&(getSmallestNode()));
00517     } else {
00518         leaves.push_back(NodeHandle::UNSPECIFIED_NODE);
00519         bigger = leaves.begin() + (numberOfLeaves >> 1);
00520         smaller = bigger - 1;
00521         ask = static_cast<const TransportAddress*>(&(getBiggestNode()));
00522     }
00523 
00524     assert(ask->isUnspecified() || *ask != overlay->getThisNode());
00525 
00526     balanceLeafSet();
00527     LEAF_TEST();
00528 
00529     assert(ask->isUnspecified() || *ask != overlay->getThisNode());
00530 
00531     if (! ask->isUnspecified())
00532         awaitingRepair[*ask] = PLSRepairData(simTime(), left);
00533 
00534     return *ask;
00535 }
00536 
00537 const TransportAddress& PastryLeafSet::repair(const PastryStateMessage* msg,
00538                                               const PastryStateMsgProximity* prox)
00539 {
00540     std::map<TransportAddress, PLSRepairData>::iterator it;
00541     const TransportAddress* ask;
00542     bool left;
00543 
00544     simtime_t now = simTime();
00545 
00546     // first eliminate outdated entries in awaitingRepair:
00547     for (it = awaitingRepair.begin(); it != awaitingRepair.end();) {
00548         if (it->second.ts < (now - repairTimeout)) {
00549             awaitingRepair.erase(it++);
00550         }
00551         else it++;
00552     }
00553 
00554     // don't expect any more repair messages:
00555     if (awaitingRepair.empty()) return TransportAddress::UNSPECIFIED_NODE;
00556 
00557     // look for source node in our list:
00558     if ( (it = awaitingRepair.find(msg->getSender())) == awaitingRepair.end() )
00559         return TransportAddress::UNSPECIFIED_NODE;
00560 
00561     // which side of the LeafSet is affected:
00562     left = it->second.left;
00563 
00564     // remove source node from list:
00565     awaitingRepair.erase(it);
00566 
00567     // merge info from repair message:
00568     if (mergeState(msg, prox) || isFull || !wasFull) {
00569         EV << "[PastryLeafSet::repair()]\n"
00570            << "    LeafSet repair was successful."
00571            << endl;
00572         return TransportAddress::UNSPECIFIED_NODE;
00573     } else {
00574         // repair did not succeed, try again:
00575         ask = &( left ? getSmallestNode() : getBiggestNode() );
00576         if (ask->isUnspecified() || *ask == msg->getSender()) {
00577             EV << "[PastryLeafSet::repair()]\n"
00578                << "    LeafSet giving up repair attempt."
00579                << endl;
00580             return TransportAddress::UNSPECIFIED_NODE;
00581         } else {
00582             awaitingRepair[*ask] = PLSRepairData(simTime(), left);
00583         }
00584         return *ask;
00585     }
00586 }
00587 
00588 PastryNewLeafsMessage* PastryLeafSet::getNewLeafsMessage(void)
00589 {
00590     std::vector<NodeHandle>::const_iterator it;
00591     PastryNewLeafsMessage* msg;
00592     uint32_t i = 0;
00593 
00594     if (! newLeafs) return NULL;
00595     newLeafs = false;
00596 
00597     msg = new PastryNewLeafsMessage("PastryNewLeafs");
00598 
00599     msg->setLeafsArraySize(numberOfLeaves);
00600     for (it = leaves.begin(); it != leaves.end(); it++)
00601         msg->setLeafs(i++, *it);
00602 
00603     msg->setBitLength(PASTRYNEWLEAFS_L(msg));
00604     return msg;
00605 }
Generated on Wed May 26 16:21:14 2010 for OverSim by  doxygen 1.6.3