PeerStorage.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2010 Karlsruhe Institute of Technology (KIT),
00003 //                    Institute of Telematics
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 //
00019 
00025 #include <PeerInfo.h>
00026 #include <NodeHandle.h>
00027 
00028 #include "PeerStorage.h"
00029 
00030 PeerStorage::~PeerStorage()
00031 {
00032     PeerHashMap::iterator it;
00033     for (it = peerHashMap.begin(); it != peerHashMap.end(); it++) {
00034         delete it->second.info;
00035         delete it->second.node;
00036     }
00037 }
00038 
00039 size_t PeerStorage::size()
00040 {
00041     return peerHashMap.size();
00042 }
00043 
00044 const PeerHashMap::iterator PeerStorage::find(const IPvXAddress& ip)
00045 {
00046     return peerHashMap.find(ip);
00047 }
00048 
00049 const PeerHashMap::iterator PeerStorage::begin()
00050 {
00051     return peerHashMap.begin();
00052 }
00053 
00054 const PeerHashMap::iterator PeerStorage::end()
00055 {
00056     return peerHashMap.end();
00057 }
00058 
00059 size_t PeerStorage::offsetSize()
00060 {
00061     return 1<<2;
00062 }
00063 
00064 uint8_t PeerStorage::calcOffset(bool bootstrapped, bool malicious)
00065 {
00066     uint8_t offset = 0;
00067     if (bootstrapped) offset += 1<<0;
00068     if (malicious) offset += 1<<1;
00069     return offset;
00070 }
00071 
00072 void PeerStorage::insertMapIteratorIntoVector(PeerHashMap::iterator it)
00073 {
00074     PeerInfo* peerInfo = it->second.info;
00075     bool bootstrapped = peerInfo->isBootstrapped();
00076     bool malicious = peerInfo->isMalicious();
00077     size_t partition = peerInfo->getTypeID();
00078     size_t offset = calcOffset(bootstrapped, malicious);
00079     size_t partitionIndex = partition*offsetSize()+offset;
00080 
00081 #if 0
00082     std::cout << "INSERT " << it->first << " partitionIndex:"
00083               << partitionIndex
00084               << " bootstrapped:" << bootstrapped << " malicious:"
00085               << malicious << std::endl;
00086 #endif
00087 
00088     if (peerVector.size() < (partition + 1)*offsetSize()) {
00089         int i = peerVector.size();
00090         peerVector.resize(offsetSize()*(partition + 1));
00091         freeVector.resize(offsetSize()*(partition + 1));
00092         while (i < (int)(peerVector.size())) {
00093             peerVector[i++].reserve(30000);
00094             freeVector[i++].reserve(30000);
00095         }
00096     }
00097 
00098     size_t index = -1;
00099 
00100     if ((freeVector.size() >= (partition + 1)*offsetSize()) &&
00101             (freeVector[partitionIndex].size())) {
00102 
00103         index = freeVector[partitionIndex].back();
00104         freeVector[partitionIndex].pop_back();
00105         peerVector[partitionIndex][index] = it;
00106         //std::cout << "\t REUSING position " << index << std::endl;
00107     } else {
00108         index = peerVector[partitionIndex].size();
00109         peerVector[partitionIndex].push_back(it);
00110         //std::cout << "\t APPENDING at position " << index << std::endl;
00111     }
00112 
00113     it->second.peerVectorIndex = index;
00114 }
00115 
00116 void PeerStorage::removeMapIteratorFromVector(PeerHashMap::iterator it)
00117 {
00118     PeerInfo* peerInfo = it->second.info;
00119     bool bootstrapped = peerInfo->isBootstrapped();
00120     bool malicious = peerInfo->isMalicious();
00121     size_t partition = peerInfo->getTypeID();
00122     size_t offset = calcOffset(bootstrapped, malicious);
00123     size_t index = it->second.peerVectorIndex;
00124     size_t partitionIndex = partition*offsetSize()+offset;
00125 
00126     if (peerVector[partitionIndex].size() == (index + 1)) {
00127         peerVector[partitionIndex].pop_back();
00128     } else {
00129         peerVector[partitionIndex][index] = peerHashMap.end();
00130         freeVector[partitionIndex].push_back(index);
00131     }
00132     //std::cout << "ERASE " << it->first << " partitionIndex:" << partitionIndex
00133     //          << " index: " << index << std::endl;
00134 }
00135 
00136 std::pair<const PeerHashMap::iterator, bool> PeerStorage::insert(const std::pair<IPvXAddress, BootstrapEntry>& element)
00137 {
00138     std::pair<PeerHashMap::iterator, bool> ret;
00139 
00140     ret = peerHashMap.insert(element);
00141 
00142     if (ret.second) {
00143         insertMapIteratorIntoVector(ret.first);
00144     }
00145 
00146     return ret;
00147 }
00148 
00149 void PeerStorage::erase(const PeerHashMap::iterator it)
00150 {
00151     removeMapIteratorFromVector(it);
00152     delete it->second.info;
00153     delete it->second.node;
00154     peerHashMap.erase(it);
00155 }
00156 
00157 void PeerStorage::setMalicious(const PeerHashMap::iterator it, bool malicious)
00158 {
00159     if (it == peerHashMap.end()) {
00160         throw cRuntimeError("GlobalNodeList::setMalicious(): Node not found!");
00161     }
00162 
00163     removeMapIteratorFromVector(it);
00164     it->second.info->setMalicious(malicious);
00165     insertMapIteratorIntoVector(it);
00166 }
00167 
00168 void PeerStorage::setBootstrapped(const PeerHashMap::iterator it, bool bootstrapped)
00169 {
00170     if (it == peerHashMap.end()) {
00171         throw cRuntimeError("GlobalNodeList::setMalicious(): Node not found!");
00172     }
00173 
00174     removeMapIteratorFromVector(it);
00175     //std::cout << "setBootstrapped: " << bootstrapped << std::endl;
00176     it->second.info->setBootstrapped(bootstrapped);
00177     insertMapIteratorIntoVector(it);
00178 }
00179 
00180 const PeerHashMap::iterator PeerStorage::getRandomNode(int32_t nodeType,
00181                                                        bool bootstrappedNeeded,
00182                                                        bool inoffensiveNeeded)
00183 {
00184     if (peerHashMap.size() == 0) {
00185         std::cout << "getRandomNode: empty!" << std::endl;
00186         return peerHashMap.end();
00187     }
00188 
00189     size_t sum = 0;
00190 
00191     //std::cout << "getRandomNode(): nodeType: " << nodeType << " boostrapped: "
00192     //          << bootstrappedNeeded << " inoffensive: " << inoffensiveNeeded
00193     //          << std::endl;
00194 
00195     for (uint i = 0; i < peerVector.size(); i++) {
00196         if (((nodeType > -1) && ((uint)nodeType != i/offsetSize())) ||
00197                 (bootstrappedNeeded && !(i & 1)) ||
00198                 (inoffensiveNeeded && (i & 2))) {
00199             continue;
00200         }
00201         //std::cout << "Using i=" << i << std::endl;
00202         sum += (peerVector[i].size() - freeVector[i].size());
00203         //std::cout << "new sum: " << sum << std::endl;
00204     }
00205 
00206     if (sum == 0) {
00207         return peerHashMap.end();
00208     }
00209 
00210     size_t random = intuniform(1, sum);
00211     uint i = 0;
00212 
00213     while ((i < peerVector.size())) {
00214         if (((nodeType > -1) && ((uint)nodeType != i/offsetSize())) ||
00215                 (bootstrappedNeeded && !(i & 1)) ||
00216                 (inoffensiveNeeded && (i & 2))) {
00217             i++;
00218             continue;
00219         } else if ((peerVector[i].size() - freeVector[i].size()) < random) {
00220             random -= peerVector[i].size() - freeVector[i].size();
00221             i++;
00222         } else {
00223             break;
00224         }
00225     }
00226 
00227     random = intuniform(1, peerVector[i].size());
00228     PeerHashMap::iterator it = peerVector[i][random-1];
00229     while (it == peerHashMap.end()) {
00230         if (random == peerVector[i].size()) {
00231             random = 0;
00232         }
00233         it = peerVector[i][(++random)-1];
00234     }
00235     //std::cout << "Using node from vector i=" << i << " and position=" << random-1 << std::endl;
00236 
00237     return it;
00238 }