X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Faddrman.h;h=fa70a079689470f3092709b1267e1a2e4ae8cbcd;hb=18770118e846622f59a86f9937a33da0bb761775;hp=5f1d7b2af9c24a63709ee502d6e9b59b094f0dcf;hpb=700e5a4d86d5180e6bb905c25a9e05695617f445;p=novacoin.git diff --git a/src/addrman.h b/src/addrman.h index 5f1d7b2..fa70a07 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -1,12 +1,13 @@ // Copyright (c) 2012 Pieter Wuille // Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef _BITCOIN_ADDRMAN #define _BITCOIN_ADDRMAN 1 #include "netbase.h" #include "protocol.h" #include "util.h" +#include "sync.h" #include @@ -22,13 +23,13 @@ private: // where knowledge about this address first came from CNetAddr source; - // last succesfull connection by us + // last successful connection by us int64 nLastSuccess; // last try whatsoever by us: // int64 CAddress::nLastTry - // connection attempts since last succesful attempt + // connection attempts since last successful attempt int nAttempts; // reference count in new sets (memory only) @@ -116,7 +117,7 @@ public: // * Bucket selection is based on cryptographic hashing, using a randomly-generated 256-bit key, which should not // be observable by adversaries. // * Several indexes are kept for high performance. Defining DEBUG_ADDRMAN will introduce frequent (and expensive) -// consistency checks for the entire datastructure. +// consistency checks for the entire data structure. // total number of buckets for tried addresses #define ADDRMAN_TRIED_BUCKET_COUNT 64 @@ -173,13 +174,13 @@ private: // last used nId int nIdCount; - // table with information about all nId's + // table with information about all nIds std::map mapInfo; // find an nId based on its network address std::map mapAddr; - // randomly-ordered vector of all nId's + // randomly-ordered vector of all nIds std::vector vRandom; // number of "tried" entries @@ -204,7 +205,7 @@ protected: CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = NULL); // Swap two elements in vRandom. - void SwapRandom(int nRandomPos1, int nRandomPos2); + void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2); // Return position in given bucket to replace. int SelectTried(int nKBucket); @@ -213,7 +214,7 @@ protected: // This is the only place where actual deletes occur. // They are never deleted while in the "tried" table, only possibly evicted back to the "new" table. int ShrinkNew(int nUBucket); - + // Move an entry from the "new" table(s) to the "tried" table // @pre vvUnkown[nOrigin].count(nId) != 0 void MakeTried(CAddrInfo& info, int nId, int nOrigin); @@ -244,6 +245,7 @@ protected: public: +#ifndef _MSC_VER IMPLEMENT_SERIALIZE (({ // serialized format: @@ -252,8 +254,8 @@ public: // * nNew // * nTried // * number of "new" buckets - // * all nNew addrinfo's in vvNew - // * all nTried addrinfo's in vvTried + // * all nNew addrinfos in vvNew + // * all nTried addrinfos in vvTried // * for each bucket: // * number of elements // * for each element: index @@ -266,8 +268,8 @@ public: // // This format is more complex, but significantly smaller (at most 1.5 MiB), and supports // changes to the ADDRMAN_ parameters without breaking the on-disk structure. - CRITICAL_BLOCK(cs) { + LOCK(cs); unsigned char nVersion = 0; READWRITE(nVersion); READWRITE(nKey); @@ -377,7 +379,183 @@ public: } } });) +#else + IMPLEMENT_SERIALIZE + ( + LOCK(cs); + unsigned char + nVersion = 0; + + READWRITE(nVersion); + READWRITE(nKey); + READWRITE(nNew); + READWRITE(nTried); + + CAddrMan + *am = const_cast(this); + + if (fWrite) + { + int + nUBuckets = ADDRMAN_NEW_BUCKET_COUNT; + + READWRITE(nUBuckets); +/************ + std::map + mapUnkIds; +************/ + int + nIds = 0; + for (std::map::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++) + { + if (nIds == nNew) + break; // this means nNew was wrong, oh ow + mapUnkIds[(*it).first] = nIds; + + CAddrInfo + &info = (*it).second; + + if (info.nRefCount) + { + READWRITE(info); + nIds++; + } + } + nIds = 0; + for (std::map::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++) + { + if (nIds == nTried) + break; /* this means nTried was wrong, oh ow */ + + CAddrInfo + &info = (*it).second; + + if (info.fInTried) + { + READWRITE(info); + nIds++; + } + } + for ( + std::vector >::iterator it = am->vvNew.begin(); + it != am->vvNew.end(); + it++ + ) + { + std::set + &vNew = (*it); + + int + nSize = int( vNew.size() ); + + READWRITE(nSize); + for (std::set::iterator it2 = vNew.begin(); it2 != vNew.end(); it2++) + { + int + nIndex = mapUnkIds[*it2]; + READWRITE(nIndex); + } + } + } + else + { + int + nUBuckets = 0; + + READWRITE(nUBuckets); + am->nIdCount = 0; + am->mapInfo.clear(); + am->mapAddr.clear(); + am->vRandom.clear(); + am->vvTried = + std::vector >( + ADDRMAN_TRIED_BUCKET_COUNT, + std::vector(0) + ); + am->vvNew = + std::vector >( + ADDRMAN_NEW_BUCKET_COUNT, + std::set() + ); + for (int n = 0; n < am->nNew; n++) + { + CAddrInfo + &info = am->mapInfo[n]; + READWRITE(info); + am->mapAddr[info] = n; + info.nRandomPos = int( vRandom.size() ); + am->vRandom.push_back(n); + if (nUBuckets != ADDRMAN_NEW_BUCKET_COUNT) + { + am->vvNew[info.GetNewBucket(am->nKey)].insert(n); + info.nRefCount++; + } + } + am->nIdCount = am->nNew; + + int + nLost = 0; + + for (int n = 0; n < am->nTried; n++) + { + CAddrInfo + info; + + READWRITE(info); + + std::vector + &vTried = am->vvTried[info.GetTriedBucket(am->nKey)]; + + if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE) + { + info.nRandomPos = int( vRandom.size() ); + info.fInTried = true; + am->vRandom.push_back(am->nIdCount); + am->mapInfo[am->nIdCount] = info; + am->mapAddr[info] = am->nIdCount; + vTried.push_back(am->nIdCount); + am->nIdCount++; + } + else + { + nLost++; + } + } + am->nTried -= nLost; + for (int b = 0; b < nUBuckets; b++) + { + std::set + &vNew = am->vvNew[b]; + + int + nSize = 0; + + READWRITE(nSize); + for (int n = 0; n < nSize; n++) + { + int + nIndex = 0; + + READWRITE(nIndex); + + CAddrInfo + &info = am->mapInfo[nIndex]; + + if ( + (nUBuckets == ADDRMAN_NEW_BUCKET_COUNT) && + (info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS) + ) + { + info.nRefCount++; + vNew.insert(nIndex); + } + } + } + } + ) + +#endif //_MSC_VER CAddrMan() : vRandom(0), vvTried(ADDRMAN_TRIED_BUCKET_COUNT, std::vector(0)), vvNew(ADDRMAN_NEW_BUCKET_COUNT, std::set()) { nKey.resize(32); @@ -398,8 +576,8 @@ public: void Check() { #ifdef DEBUG_ADDRMAN - CRITICAL_BLOCK(cs) { + LOCK(cs); int err; if ((err=Check_())) printf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err); @@ -411,8 +589,8 @@ public: bool Add(const CAddress &addr, const CNetAddr& source, int64 nTimePenalty = 0) { bool fRet = false; - CRITICAL_BLOCK(cs) { + LOCK(cs); Check(); fRet |= Add_(addr, source, nTimePenalty); Check(); @@ -426,8 +604,8 @@ public: bool Add(const std::vector &vAddr, const CNetAddr& source, int64 nTimePenalty = 0) { int nAdd = 0; - CRITICAL_BLOCK(cs) { + LOCK(cs); Check(); for (std::vector::const_iterator it = vAddr.begin(); it != vAddr.end(); it++) nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0; @@ -441,8 +619,8 @@ public: // Mark an entry as accessible. void Good(const CService &addr, int64 nTime = GetAdjustedTime()) { - CRITICAL_BLOCK(cs) { + LOCK(cs); Check(); Good_(addr, nTime); Check(); @@ -452,8 +630,8 @@ public: // Mark an entry as connection attempted to. void Attempt(const CService &addr, int64 nTime = GetAdjustedTime()) { - CRITICAL_BLOCK(cs) { + LOCK(cs); Check(); Attempt_(addr, nTime); Check(); @@ -465,8 +643,8 @@ public: CAddress Select(int nUnkBias = 50) { CAddress addrRet; - CRITICAL_BLOCK(cs) { + LOCK(cs); Check(); addrRet = Select_(nUnkBias); Check(); @@ -479,8 +657,10 @@ public: { Check(); std::vector vAddr; - CRITICAL_BLOCK(cs) + { + LOCK(cs); GetAddr_(vAddr); + } Check(); return vAddr; } @@ -488,8 +668,8 @@ public: // Mark an entry as currently-connected-to. void Connected(const CService &addr, int64 nTime = GetAdjustedTime()) { - CRITICAL_BLOCK(cs) { + LOCK(cs); Check(); Connected_(addr, nTime); Check();