mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-10 00:00:29 +03:00
use DHT table for floodfills
This commit is contained in:
parent
692600dfac
commit
d40cd00cdb
@ -186,7 +186,7 @@ namespace data
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<RouterInfo> DHTTable::FindClosest (const IdentHash& h, const Filter& filter)
|
std::shared_ptr<RouterInfo> DHTTable::FindClosest (const IdentHash& h, const Filter& filter) const
|
||||||
{
|
{
|
||||||
if (filter) m_Filter = filter;
|
if (filter) m_Filter = filter;
|
||||||
auto r = FindClosest (h, m_Root, 0);
|
auto r = FindClosest (h, m_Root, 0);
|
||||||
@ -194,7 +194,7 @@ namespace data
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<RouterInfo> DHTTable::FindClosest (const IdentHash& h, DHTNode * root, int level)
|
std::shared_ptr<RouterInfo> DHTTable::FindClosest (const IdentHash& h, DHTNode * root, int level) const
|
||||||
{
|
{
|
||||||
bool split = false;
|
bool split = false;
|
||||||
do
|
do
|
||||||
@ -241,7 +241,7 @@ namespace data
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<RouterInfo> > DHTTable::FindClosest (const IdentHash& h, size_t num, const Filter& filter)
|
std::vector<std::shared_ptr<RouterInfo> > DHTTable::FindClosest (const IdentHash& h, size_t num, const Filter& filter) const
|
||||||
{
|
{
|
||||||
std::vector<std::shared_ptr<RouterInfo> > vec;
|
std::vector<std::shared_ptr<RouterInfo> > vec;
|
||||||
if (num > 0)
|
if (num > 0)
|
||||||
@ -253,7 +253,7 @@ namespace data
|
|||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DHTTable::FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector<std::shared_ptr<RouterInfo> >& hashes)
|
void DHTTable::FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector<std::shared_ptr<RouterInfo> >& hashes) const
|
||||||
{
|
{
|
||||||
if (hashes.size () >= num) return;
|
if (hashes.size () >= num) return;
|
||||||
bool split = false;
|
bool split = false;
|
||||||
@ -292,7 +292,7 @@ namespace data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DHTTable::Cleanup (Filter filter)
|
void DHTTable::Cleanup (const Filter& filter)
|
||||||
{
|
{
|
||||||
if (filter)
|
if (filter)
|
||||||
{
|
{
|
||||||
|
@ -44,20 +44,20 @@ namespace data
|
|||||||
|
|
||||||
void Insert (const std::shared_ptr<RouterInfo>& r);
|
void Insert (const std::shared_ptr<RouterInfo>& r);
|
||||||
bool Remove (const IdentHash& h);
|
bool Remove (const IdentHash& h);
|
||||||
std::shared_ptr<RouterInfo> FindClosest (const IdentHash& h, const Filter& filter = nullptr);
|
std::shared_ptr<RouterInfo> FindClosest (const IdentHash& h, const Filter& filter = nullptr) const;
|
||||||
std::vector<std::shared_ptr<RouterInfo> > FindClosest (const IdentHash& h, size_t num, const Filter& filter = nullptr);
|
std::vector<std::shared_ptr<RouterInfo> > FindClosest (const IdentHash& h, size_t num, const Filter& filter = nullptr) const;
|
||||||
|
|
||||||
void Print (std::stringstream& s);
|
void Print (std::stringstream& s);
|
||||||
size_t GetSize () const { return m_Size; };
|
size_t GetSize () const { return m_Size; };
|
||||||
void Clear ();
|
void Clear ();
|
||||||
void Cleanup (Filter filter);
|
void Cleanup (const Filter& filter);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void Insert (const std::shared_ptr<RouterInfo>& r, DHTNode * root, int level); // recursive
|
void Insert (const std::shared_ptr<RouterInfo>& r, DHTNode * root, int level); // recursive
|
||||||
bool Remove (const IdentHash& h, DHTNode * root, int level);
|
bool Remove (const IdentHash& h, DHTNode * root, int level);
|
||||||
std::shared_ptr<RouterInfo> FindClosest (const IdentHash& h, DHTNode * root, int level);
|
std::shared_ptr<RouterInfo> FindClosest (const IdentHash& h, DHTNode * root, int level) const;
|
||||||
void FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector<std::shared_ptr<RouterInfo> >& hashes);
|
void FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector<std::shared_ptr<RouterInfo> >& hashes) const;
|
||||||
void Cleanup (DHTNode * root);
|
void Cleanup (DHTNode * root);
|
||||||
void Print (std::stringstream& s, DHTNode * root, int level);
|
void Print (std::stringstream& s, DHTNode * root, int level);
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ namespace data
|
|||||||
DHTNode * m_Root;
|
DHTNode * m_Root;
|
||||||
size_t m_Size;
|
size_t m_Size;
|
||||||
// transient
|
// transient
|
||||||
Filter m_Filter;
|
mutable Filter m_Filter;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ namespace data
|
|||||||
Load ();
|
Load ();
|
||||||
|
|
||||||
uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold);
|
uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold);
|
||||||
if (m_RouterInfos.size () < threshold || m_Floodfills.size () < NETDB_MIN_FLOODFILLS) // reseed if # of router less than threshold or too few floodfiils
|
if (m_RouterInfos.size () < threshold || m_Floodfills.GetSize () < NETDB_MIN_FLOODFILLS) // reseed if # of router less than threshold or too few floodfiils
|
||||||
{
|
{
|
||||||
Reseed ();
|
Reseed ();
|
||||||
}
|
}
|
||||||
@ -66,13 +66,13 @@ namespace data
|
|||||||
if (it != m_RouterInfos.end ())
|
if (it != m_RouterInfos.end ())
|
||||||
{
|
{
|
||||||
// remove own router
|
// remove own router
|
||||||
m_Floodfills.remove (it->second);
|
m_Floodfills.Remove (it->second->GetIdentHash ());
|
||||||
m_RouterInfos.erase (it);
|
m_RouterInfos.erase (it);
|
||||||
}
|
}
|
||||||
// insert own router
|
// insert own router
|
||||||
m_RouterInfos.emplace (i2p::context.GetIdentHash (), i2p::context.GetSharedRouterInfo ());
|
m_RouterInfos.emplace (i2p::context.GetIdentHash (), i2p::context.GetSharedRouterInfo ());
|
||||||
if (i2p::context.IsFloodfill ())
|
if (i2p::context.IsFloodfill ())
|
||||||
m_Floodfills.push_back (i2p::context.GetSharedRouterInfo ());
|
m_Floodfills.Insert (i2p::context.GetSharedRouterInfo ());
|
||||||
|
|
||||||
i2p::config::GetOption("persist.profiles", m_PersistProfiles);
|
i2p::config::GetOption("persist.profiles", m_PersistProfiles);
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ namespace data
|
|||||||
SaveProfiles ();
|
SaveProfiles ();
|
||||||
DeleteObsoleteProfiles ();
|
DeleteObsoleteProfiles ();
|
||||||
m_RouterInfos.clear ();
|
m_RouterInfos.clear ();
|
||||||
m_Floodfills.clear ();
|
m_Floodfills.Clear ();
|
||||||
if (m_Thread)
|
if (m_Thread)
|
||||||
{
|
{
|
||||||
m_IsRunning = false;
|
m_IsRunning = false;
|
||||||
@ -289,7 +289,7 @@ namespace data
|
|||||||
if (wasFloodfill)
|
if (wasFloodfill)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
||||||
m_Floodfills.remove (r);
|
m_Floodfills.Remove (r->GetIdentHash ());
|
||||||
}
|
}
|
||||||
m_Requests.RequestComplete (ident, nullptr);
|
m_Requests.RequestComplete (ident, nullptr);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -301,9 +301,9 @@ namespace data
|
|||||||
LogPrint (eLogDebug, "NetDb: RouterInfo floodfill status updated: ", ident.ToBase64());
|
LogPrint (eLogDebug, "NetDb: RouterInfo floodfill status updated: ", ident.ToBase64());
|
||||||
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
||||||
if (wasFloodfill)
|
if (wasFloodfill)
|
||||||
m_Floodfills.remove (r);
|
m_Floodfills.Remove (r->GetIdentHash ());
|
||||||
else if (r->IsEligibleFloodfill ())
|
else if (r->IsEligibleFloodfill ())
|
||||||
m_Floodfills.push_back (r);
|
m_Floodfills.Insert (r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -329,7 +329,7 @@ namespace data
|
|||||||
if (r->IsFloodfill () && r->IsEligibleFloodfill ())
|
if (r->IsFloodfill () && r->IsEligibleFloodfill ())
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
||||||
m_Floodfills.push_back (r);
|
m_Floodfills.Insert (r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -530,7 +530,7 @@ namespace data
|
|||||||
if (m_RouterInfos.emplace (r->GetIdentHash (), r).second)
|
if (m_RouterInfos.emplace (r->GetIdentHash (), r).second)
|
||||||
{
|
{
|
||||||
if (r->IsFloodfill () && r->IsEligibleFloodfill ())
|
if (r->IsFloodfill () && r->IsEligibleFloodfill ())
|
||||||
m_Floodfills.push_back (r);
|
m_Floodfills.Insert (r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -614,7 +614,7 @@ namespace data
|
|||||||
{
|
{
|
||||||
// make sure we cleanup netDb from previous attempts
|
// make sure we cleanup netDb from previous attempts
|
||||||
m_RouterInfos.clear ();
|
m_RouterInfos.clear ();
|
||||||
m_Floodfills.clear ();
|
m_Floodfills.Clear ();
|
||||||
|
|
||||||
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch();
|
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch();
|
||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
@ -622,14 +622,14 @@ namespace data
|
|||||||
for (const auto& path : files)
|
for (const auto& path : files)
|
||||||
LoadRouterInfo (path, ts);
|
LoadRouterInfo (path, ts);
|
||||||
|
|
||||||
LogPrint (eLogInfo, "NetDb: ", m_RouterInfos.size(), " routers loaded (", m_Floodfills.size (), " floodfils)");
|
LogPrint (eLogInfo, "NetDb: ", m_RouterInfos.size(), " routers loaded (", m_Floodfills.GetSize (), " floodfils)");
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetDb::SaveUpdated ()
|
void NetDb::SaveUpdated ()
|
||||||
{
|
{
|
||||||
int updatedCount = 0, deletedCount = 0, deletedFloodfillsCount = 0;
|
int updatedCount = 0, deletedCount = 0, deletedFloodfillsCount = 0;
|
||||||
auto total = m_RouterInfos.size ();
|
auto total = m_RouterInfos.size ();
|
||||||
auto totalFloodfills = m_Floodfills.size ();
|
auto totalFloodfills = m_Floodfills.GetSize ();
|
||||||
uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL;
|
uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL;
|
||||||
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch();
|
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch();
|
||||||
auto uptime = i2p::context.GetUptime ();
|
auto uptime = i2p::context.GetUptime ();
|
||||||
@ -721,11 +721,10 @@ namespace data
|
|||||||
// clean up expired floodfills or not floodfills anymore
|
// clean up expired floodfills or not floodfills anymore
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
||||||
for (auto it = m_Floodfills.begin (); it != m_Floodfills.end ();)
|
m_Floodfills.Cleanup ([](const std::shared_ptr<RouterInfo>& r)->bool
|
||||||
if ((*it)->IsUnreachable () || !(*it)->IsFloodfill ())
|
{
|
||||||
it = m_Floodfills.erase (it);
|
return r && r->IsFloodfill () && !r->IsUnreachable ();
|
||||||
else
|
});
|
||||||
it++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1362,74 +1361,37 @@ namespace data
|
|||||||
std::shared_ptr<const RouterInfo> NetDb::GetClosestFloodfill (const IdentHash& destination,
|
std::shared_ptr<const RouterInfo> NetDb::GetClosestFloodfill (const IdentHash& destination,
|
||||||
const std::set<IdentHash>& excluded) const
|
const std::set<IdentHash>& excluded) const
|
||||||
{
|
{
|
||||||
std::shared_ptr<const RouterInfo> r;
|
|
||||||
XORMetric minMetric;
|
|
||||||
IdentHash destKey = CreateRoutingKey (destination);
|
IdentHash destKey = CreateRoutingKey (destination);
|
||||||
minMetric.SetMax ();
|
|
||||||
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
||||||
for (const auto& it: m_Floodfills)
|
return m_Floodfills.FindClosest (destKey, [&excluded](const std::shared_ptr<RouterInfo>& r)->bool
|
||||||
{
|
{
|
||||||
if (!it->IsUnreachable () && !it->GetProfile ()->IsUnreachable ())
|
return r && !r->IsUnreachable () && !r->GetProfile ()->IsUnreachable () &&
|
||||||
{
|
!excluded.count (r->GetIdentHash ());
|
||||||
XORMetric m = destKey ^ it->GetIdentHash ();
|
});
|
||||||
if (m < minMetric && !excluded.count (it->GetIdentHash ()))
|
|
||||||
{
|
|
||||||
minMetric = m;
|
|
||||||
r = it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<IdentHash> NetDb::GetClosestFloodfills (const IdentHash& destination, size_t num,
|
std::vector<IdentHash> NetDb::GetClosestFloodfills (const IdentHash& destination, size_t num,
|
||||||
std::set<IdentHash>& excluded, bool closeThanUsOnly) const
|
std::set<IdentHash>& excluded, bool closeThanUsOnly) const
|
||||||
{
|
{
|
||||||
struct Sorted
|
std::vector<IdentHash> res;
|
||||||
{
|
|
||||||
std::shared_ptr<const RouterInfo> r;
|
|
||||||
XORMetric metric;
|
|
||||||
bool operator< (const Sorted& other) const { return metric < other.metric; };
|
|
||||||
};
|
|
||||||
|
|
||||||
std::set<Sorted> sorted;
|
|
||||||
IdentHash destKey = CreateRoutingKey (destination);
|
IdentHash destKey = CreateRoutingKey (destination);
|
||||||
XORMetric ourMetric;
|
std::vector<std::shared_ptr<RouterInfo> > v;
|
||||||
if (closeThanUsOnly) ourMetric = destKey ^ i2p::context.GetIdentHash ();
|
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
||||||
for (const auto& it: m_Floodfills)
|
v = m_Floodfills.FindClosest (destKey, num, [&excluded](const std::shared_ptr<RouterInfo>& r)->bool
|
||||||
{
|
{
|
||||||
if (!it->IsUnreachable () && !it->GetProfile ()->IsUnreachable ())
|
return r && !r->IsUnreachable () && !r->GetProfile ()->IsUnreachable () &&
|
||||||
{
|
!excluded.count (r->GetIdentHash ());
|
||||||
XORMetric m = destKey ^ it->GetIdentHash ();
|
});
|
||||||
if (closeThanUsOnly && ourMetric < m) continue;
|
|
||||||
if (sorted.size () < num)
|
|
||||||
sorted.insert ({it, m});
|
|
||||||
else if (m < sorted.rbegin ()->metric)
|
|
||||||
{
|
|
||||||
sorted.insert ({it, m});
|
|
||||||
sorted.erase (std::prev (sorted.end ()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (v.empty ()) return res;
|
||||||
|
|
||||||
std::vector<IdentHash> res;
|
XORMetric ourMetric;
|
||||||
size_t i = 0;
|
if (closeThanUsOnly) ourMetric = destKey ^ i2p::context.GetIdentHash ();
|
||||||
for (const auto& it: sorted)
|
for (auto& it: v)
|
||||||
{
|
{
|
||||||
if (i < num)
|
if (closeThanUsOnly && ourMetric < (destKey ^ it->GetIdentHash ())) break;
|
||||||
{
|
res.push_back (it->GetIdentHash ());
|
||||||
const auto& ident = it.r->GetIdentHash ();
|
|
||||||
if (!excluded.count (ident))
|
|
||||||
{
|
|
||||||
res.push_back (ident);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <list>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@ -31,6 +30,7 @@
|
|||||||
#include "Family.h"
|
#include "Family.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "KadDHT.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
@ -110,7 +110,7 @@ namespace data
|
|||||||
|
|
||||||
// for web interface
|
// for web interface
|
||||||
int GetNumRouters () const { return m_RouterInfos.size (); };
|
int GetNumRouters () const { return m_RouterInfos.size (); };
|
||||||
int GetNumFloodfills () const { return m_Floodfills.size (); };
|
int GetNumFloodfills () const { return m_Floodfills.GetSize (); };
|
||||||
int GetNumLeaseSets () const { return m_LeaseSets.size (); };
|
int GetNumLeaseSets () const { return m_LeaseSets.size (); };
|
||||||
|
|
||||||
/** visit all lease sets we currently store */
|
/** visit all lease sets we currently store */
|
||||||
@ -164,7 +164,7 @@ namespace data
|
|||||||
mutable std::mutex m_RouterInfosMutex;
|
mutable std::mutex m_RouterInfosMutex;
|
||||||
std::unordered_map<IdentHash, std::shared_ptr<RouterInfo> > m_RouterInfos;
|
std::unordered_map<IdentHash, std::shared_ptr<RouterInfo> > m_RouterInfos;
|
||||||
mutable std::mutex m_FloodfillsMutex;
|
mutable std::mutex m_FloodfillsMutex;
|
||||||
std::list<std::shared_ptr<RouterInfo> > m_Floodfills;
|
DHTTable m_Floodfills;
|
||||||
|
|
||||||
bool m_IsRunning;
|
bool m_IsRunning;
|
||||||
std::thread * m_Thread;
|
std::thread * m_Thread;
|
||||||
|
Loading…
Reference in New Issue
Block a user