77#include < stdio.h>
88#include < stdlib.h>
99#include < getopt.h>
10+ #include < atomic>
1011
1112#include " bitcoin.h"
1213#include " db.h"
@@ -194,13 +195,18 @@ extern "C" int GetIPList(void *thread, char *requestedHostname, addr_t *addr, in
194195
195196class CDnsThread {
196197public:
198+ struct FlagSpecificData {
199+ int nIPv4, nIPv6;
200+ std::vector<addr_t > cache;
201+ time_t cacheTime;
202+ unsigned int cacheHits;
203+ FlagSpecificData () : nIPv4(0 ), nIPv6(0 ), cacheTime(0 ), cacheHits(0 ) {}
204+ };
205+
197206 dns_opt_t dns_opt; // must be first
198207 const int id;
199- std::map<uint64_t , vector<addr_t > > cache;
200- int nIPv4, nIPv6;
201- std::map<uint64_t , time_t > cacheTime;
202- unsigned int cacheHits;
203- uint64_t dbQueries;
208+ std::map<uint64_t , FlagSpecificData> perflag;
209+ std::atomic<uint64_t > dbQueries;
204210 std::set<uint64_t > filterWhitelist;
205211
206212 void cacheHit (uint64_t requestedFlags, bool force = false ) {
@@ -210,34 +216,35 @@ class CDnsThread {
210216 nets[NET_IPV6] = true ;
211217 }
212218 time_t now = time (NULL );
213- cacheHits++;
214- if (force || cacheHits > (cache[requestedFlags].size ()*cache[requestedFlags].size ()/400 ) || (cacheHits*cacheHits > cache[requestedFlags].size () / 20 && (now - cacheTime[requestedFlags] > 5 ))) {
219+ FlagSpecificData thisflag = perflag[requestedFlags];
220+ thisflag.cacheHits ++;
221+ if (force || thisflag.cacheHits * 400 > (thisflag.cache .size ()*thisflag.cache .size ()) || (thisflag.cacheHits *thisflag.cacheHits * 20 > thisflag.cache .size () && (now - thisflag.cacheTime > 5 ))) {
215222 set<CNetAddr> ips;
216223 db.GetIPs (ips, requestedFlags, 1000 , nets);
217224 dbQueries++;
218- cache[requestedFlags] .clear ();
219- nIPv4 = 0 ;
220- nIPv6 = 0 ;
221- cache[requestedFlags] .reserve (ips.size ());
225+ thisflag. cache .clear ();
226+ thisflag. nIPv4 = 0 ;
227+ thisflag. nIPv6 = 0 ;
228+ thisflag. cache .reserve (ips.size ());
222229 for (set<CNetAddr>::iterator it = ips.begin (); it != ips.end (); it++) {
223230 struct in_addr addr;
224231 struct in6_addr addr6;
225232 if ((*it).GetInAddr (&addr)) {
226233 addr_t a;
227234 a.v = 4 ;
228235 memcpy (&a.data .v4 , &addr, 4 );
229- cache[requestedFlags] .push_back (a);
230- nIPv4++;
236+ thisflag. cache .push_back (a);
237+ thisflag. nIPv4 ++;
231238 } else if ((*it).GetIn6Addr (&addr6)) {
232239 addr_t a;
233240 a.v = 6 ;
234241 memcpy (&a.data .v6 , &addr6, 16 );
235- cache[requestedFlags] .push_back (a);
236- nIPv6++;
242+ thisflag. cache .push_back (a);
243+ thisflag. nIPv6 ++;
237244 }
238245 }
239- cacheHits = 0 ;
240- cacheTime[requestedFlags] = now;
246+ thisflag. cacheHits = 0 ;
247+ thisflag. cacheTime = now;
241248 }
242249 }
243250
@@ -250,12 +257,8 @@ class CDnsThread {
250257 dns_opt.cb = GetIPList;
251258 dns_opt.port = opts->nPort ;
252259 dns_opt.nRequests = 0 ;
253- cache.clear ();
254- cacheTime.clear ();
255- cacheHits = 0 ;
256260 dbQueries = 0 ;
257- nIPv4 = 0 ;
258- nIPv6 = 0 ;
261+ perflag.clear ();
259262 filterWhitelist = opts->filter_whitelist ;
260263 }
261264
@@ -280,8 +283,9 @@ extern "C" int GetIPList(void *data, char *requestedHostname, addr_t* addr, int
280283 else if (strcasecmp (requestedHostname, thread->dns_opt .host ))
281284 return 0 ;
282285 thread->cacheHit (requestedFlags);
283- unsigned int size = thread->cache [requestedFlags].size ();
284- unsigned int maxmax = (ipv4 ? thread->nIPv4 : 0 ) + (ipv6 ? thread->nIPv6 : 0 );
286+ auto & thisflag = thread->perflag [requestedFlags];
287+ unsigned int size = thisflag.cache .size ();
288+ unsigned int maxmax = (ipv4 ? thisflag.nIPv4 : 0 ) + (ipv6 ? thisflag.nIPv6 : 0 );
285289 if (max > size)
286290 max = size;
287291 if (max > maxmax)
@@ -290,16 +294,16 @@ extern "C" int GetIPList(void *data, char *requestedHostname, addr_t* addr, int
290294 while (i<max) {
291295 int j = i + (rand () % (size - i));
292296 do {
293- bool ok = (ipv4 && thread-> cache [requestedFlags] [j].v == 4 ) ||
294- (ipv6 && thread-> cache [requestedFlags] [j].v == 6 );
297+ bool ok = (ipv4 && thisflag. cache [j].v == 4 ) ||
298+ (ipv6 && thisflag. cache [j].v == 6 );
295299 if (ok) break ;
296300 j++;
297301 if (j==size)
298302 j=i;
299303 } while (1 );
300- addr[i] = thread-> cache [requestedFlags] [j];
301- thread-> cache [requestedFlags][ j] = thread-> cache [requestedFlags] [i];
302- thread-> cache [requestedFlags] [i] = addr[i];
304+ addr[i] = thisflag. cache [j];
305+ thisflag. cache [j] = thisflag. cache [i];
306+ thisflag. cache [i] = addr[i];
303307 i++;
304308 }
305309 return max;
@@ -310,6 +314,7 @@ vector<CDnsThread*> dnsThread;
310314extern " C" void * ThreadDNS (void * arg) {
311315 CDnsThread *thread = (CDnsThread*)arg;
312316 thread->run ();
317+ return nullptr ;
313318}
314319
315320int StatCompare (const CAddrReport& a, const CAddrReport& b) {
@@ -346,7 +351,7 @@ extern "C" void* ThreadDumper(void*) {
346351 double stat[5 ]={0 ,0 ,0 ,0 ,0 };
347352 for (vector<CAddrReport>::const_iterator it = v.begin (); it < v.end (); it++) {
348353 CAddrReport rep = *it;
349- fprintf (d, " %-47s %4d %11" PRId64" %6.2f%% %6.2f%% %6.2f%% %6.2f%% %6.2f%% %6i %08" PRIx64" %5i \" %s\"\n " , rep.ip .ToString ().c_str (), (int )rep.fGood , rep.lastSuccess , 100.0 *rep.uptime [0 ], 100.0 *rep.uptime [1 ], 100.0 *rep.uptime [2 ], 100.0 *rep.uptime [3 ], 100.0 *rep.uptime [4 ], rep.blocks , rep.services , rep.clientVersion , rep.clientSubVersion .c_str ());
354+ fprintf (d, " %-47s %4d %11" PRId64 " %6.2f%% %6.2f%% %6.2f%% %6.2f%% %6.2f%% %6i %08" PRIx64 " %5i \" %s\"\n " , rep.ip .ToString ().c_str (), (int )rep.fGood , rep.lastSuccess , 100.0 *rep.uptime [0 ], 100.0 *rep.uptime [1 ], 100.0 *rep.uptime [2 ], 100.0 *rep.uptime [3 ], 100.0 *rep.uptime [4 ], rep.blocks , rep.services , rep.clientVersion , rep.clientSubVersion .c_str ());
350355 stat[0 ] += rep.uptime [0 ];
351356 stat[1 ] += rep.uptime [1 ];
352357 stat[2 ] += rep.uptime [2 ];
@@ -387,6 +392,7 @@ extern "C" void* ThreadStats(void*) {
387392 printf (" %s %i/%i available (%i tried in %is, %i new, %i active), %i banned; %llu DNS requests, %llu db queries" , c, stats.nGood , stats.nAvail , stats.nTracked , stats.nAge , stats.nNew , stats.nAvail - stats.nTracked - stats.nNew , stats.nBanned , (unsigned long long )requests, (unsigned long long )queries);
388393 Sleep (1000 );
389394 } while (1 );
395+ return nullptr ;
390396}
391397
392398static const string mainnet_seeds[] = {" dnsseed.bluematt.me" , " bitseed.xf2.org" , " dnsseed.bitcoin.dashjr.org" , " seed.bitcoin.sipa.be" , " " };
@@ -411,6 +417,7 @@ extern "C" void* ThreadSeeder(void*) {
411417 }
412418 Sleep (1800000 );
413419 } while (1 );
420+ return nullptr ;
414421}
415422
416423int main (int argc, char **argv) {
0 commit comments