diff --git a/NetDb.cpp b/NetDb.cpp index a274908b..e1d49c5c 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -68,19 +68,9 @@ namespace data m_Requests.Stop (); } } - - void NetDb::WaitForReady() - { - m_Ready.get_future().wait(); - } void NetDb::Run () { - try { - m_Ready.set_value(); - } catch( std::future_error & ex) { - (void) ex; - } uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0; while (m_IsRunning) { @@ -354,6 +344,50 @@ namespace data for ( const auto & item : m_RouterInfos ) v(*item.second); } + + size_t NetDb::VisitRandomRouterInfos(RouterInfoFilter filter, RouterInfoVisitor v, size_t n) + { + std::vector > found; + const size_t max_iters_per_cyle = 3; + size_t iters = max_iters_per_cyle; + while(n) + { + std::unique_lock lock(m_RouterInfosMutex); + uint32_t idx = rand () % m_RouterInfos.size (); + uint32_t i = 0; + for (const auto & it : m_RouterInfos) { + if(i >= idx) // are we at the random start point? + { + // yes, check if we want this one + if(filter(*it.second)) + { + // we have a match + --n; + found.push_back(it.second); + // reset max iterations per cycle + iters = max_iters_per_cyle; + break; + } + } + else // not there yet + ++i; + } + --iters; + // have we tried enough this cycle ? + if(!iters) { + // yes let's try the next cycle + --n; + iters = max_iters_per_cyle; + } + } + // visit the ones we found + size_t visited = 0; + for(const auto & ri : found ) { + v(*ri); + ++visited; + } + return visited; + } void NetDb::Load () { diff --git a/NetDb.h b/NetDb.h index 324feb87..294e1c83 100644 --- a/NetDb.h +++ b/NetDb.h @@ -39,6 +39,9 @@ namespace data /** function for visiting a router info we have locally */ typedef std::function RouterInfoVisitor; + + /** function for visiting a router info and determining if we want to use it */ + typedef std::function RouterInfoFilter; class NetDb { @@ -49,8 +52,6 @@ namespace data void Start (); void Stop (); - /** block until netdb is ready, call only once*/ - void WaitForReady(); bool AddRouterInfo (const uint8_t * buf, int len); bool AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len); @@ -96,6 +97,8 @@ namespace data void VisitStoredRouterInfos(RouterInfoVisitor v); /** visit all router infos we have loaded in memory, cheaper than VisitLocalRouterInfos but locks access while visiting */ void VisitRouterInfos(RouterInfoVisitor v); + /** visit N random router that match using filter, then visit them with a visitor, return number of RouterInfos that were visited */ + size_t VisitRandomRouterInfos(RouterInfoFilter f, RouterInfoVisitor v, size_t n); private: void Load (); @@ -112,7 +115,6 @@ namespace data std::shared_ptr GetRandomRouter (Filter filter) const; private: - std::promise m_Ready; mutable std::mutex m_LeaseSetsMutex; std::map > m_LeaseSets;