1
0
mirror of https://github.com/PurpleI2P/i2pd.git synced 2025-02-07 07:44:13 +00:00

cache full addresses in memory when requested or received

This commit is contained in:
orignal 2025-01-27 13:24:37 -05:00
parent bf85a69a2f
commit c3fa0ae8cc
2 changed files with 42 additions and 25 deletions

View File

@ -9,7 +9,7 @@
#include <string.h> #include <string.h>
#include <inttypes.h> #include <inttypes.h>
#include <string> #include <string>
#include <map> #include <unordered_map>
#include <fstream> #include <fstream>
#include <chrono> #include <chrono>
#include <condition_variable> #include <condition_variable>
@ -49,7 +49,7 @@ namespace client
if (m_IsPersist) if (m_IsPersist)
i2p::config::GetOption("addressbook.hostsfile", m_HostsFile); i2p::config::GetOption("addressbook.hostsfile", m_HostsFile);
} }
std::shared_ptr<const i2p::data::IdentityEx> GetAddress (const i2p::data::IdentHash& ident) const override; std::shared_ptr<const i2p::data::IdentityEx> GetAddress (const i2p::data::IdentHash& ident) override;
void AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address) override; void AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address) override;
void RemoveAddress (const i2p::data::IdentHash& ident) override; void RemoveAddress (const i2p::data::IdentHash& ident) override;
@ -72,6 +72,7 @@ namespace client
std::string etagsPath, indexPath, localPath; std::string etagsPath, indexPath, localPath;
bool m_IsPersist; bool m_IsPersist;
std::string m_HostsFile; // file to dump hosts.txt, empty if not used std::string m_HostsFile; // file to dump hosts.txt, empty if not used
std::unordered_map<i2p::data::IdentHash, std::vector<uint8_t> > m_FullAddressesCache; // ident hash -> full ident buffer
}; };
bool AddressBookFilesystemStorage::Init() bool AddressBookFilesystemStorage::Init()
@ -92,8 +93,12 @@ namespace client
return false; return false;
} }
std::shared_ptr<const i2p::data::IdentityEx> AddressBookFilesystemStorage::GetAddress (const i2p::data::IdentHash& ident) const std::shared_ptr<const i2p::data::IdentityEx> AddressBookFilesystemStorage::GetAddress (const i2p::data::IdentHash& ident)
{ {
auto it = m_FullAddressesCache.find (ident);
if (it != m_FullAddressesCache.end ())
return std::make_shared<i2p::data::IdentityEx>(it->second.data (), it->second.size ());
if (!m_IsPersist) if (!m_IsPersist)
{ {
LogPrint(eLogDebug, "Addressbook: Persistence is disabled"); LogPrint(eLogDebug, "Addressbook: Persistence is disabled");
@ -101,43 +106,55 @@ namespace client
} }
std::string filename = storage.Path(ident.ToBase32()); std::string filename = storage.Path(ident.ToBase32());
std::ifstream f(filename, std::ifstream::binary); std::ifstream f(filename, std::ifstream::binary);
if (!f.is_open ()) { if (!f.is_open ())
{
LogPrint(eLogDebug, "Addressbook: Requested, but not found: ", filename); LogPrint(eLogDebug, "Addressbook: Requested, but not found: ", filename);
return nullptr; return nullptr;
} }
f.seekg (0,std::ios::end); f.seekg (0,std::ios::end);
size_t len = f.tellg (); size_t len = f.tellg ();
if (len < i2p::data::DEFAULT_IDENTITY_SIZE) { if (len < i2p::data::DEFAULT_IDENTITY_SIZE)
{
LogPrint (eLogError, "Addressbook: File ", filename, " is too short: ", len); LogPrint (eLogError, "Addressbook: File ", filename, " is too short: ", len);
return nullptr; return nullptr;
} }
f.seekg(0, std::ios::beg); f.seekg(0, std::ios::beg);
uint8_t * buf = new uint8_t[len]; std::vector<uint8_t> buf(len);
f.read((char *)buf, len); f.read((char *)buf.data (), len);
auto address = std::make_shared<i2p::data::IdentityEx>(buf, len); if (!f)
delete[] buf; {
return address; LogPrint (eLogError, "Addressbook: Couldn't read ", filename);
return nullptr;
}
m_FullAddressesCache.try_emplace (ident, buf);
return std::make_shared<i2p::data::IdentityEx>(buf.data (), len);
} }
void AddressBookFilesystemStorage::AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address) void AddressBookFilesystemStorage::AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address)
{ {
if (!address) return;
size_t len = address->GetFullLen ();
if (!len) return; // invalid address
auto [it, inserted] = m_FullAddressesCache.try_emplace (address->GetIdentHash(), len);
if (inserted)
{
address->ToBuffer (it->second.data (), len);
if (!m_IsPersist) return; if (!m_IsPersist) return;
std::string path = storage.Path( address->GetIdentHash().ToBase32() ); std::string path = storage.Path( address->GetIdentHash().ToBase32() );
std::ofstream f (path, std::ofstream::binary | std::ofstream::out); std::ofstream f (path, std::ofstream::binary | std::ofstream::out);
if (!f.is_open ()) { if (!f.is_open ())
{
LogPrint (eLogError, "Addressbook: Can't open file ", path); LogPrint (eLogError, "Addressbook: Can't open file ", path);
return; return;
} }
size_t len = address->GetFullLen (); f.write ((const char *)it->second.data (), len);
uint8_t * buf = new uint8_t[len]; }
address->ToBuffer (buf, len);
f.write ((char *)buf, len);
delete[] buf;
} }
void AddressBookFilesystemStorage::RemoveAddress (const i2p::data::IdentHash& ident) void AddressBookFilesystemStorage::RemoveAddress (const i2p::data::IdentHash& ident)
{ {
m_FullAddressesCache.erase (ident);
if (!m_IsPersist) return; if (!m_IsPersist) return;
storage.Remove( ident.ToBase32() ); storage.Remove( ident.ToBase32() );
} }
@ -341,7 +358,7 @@ namespace client
StopSubscriptions (); StopSubscriptions ();
if (m_SubscriptionsUpdateTimer) if (m_SubscriptionsUpdateTimer)
{ {
delete m_SubscriptionsUpdateTimer; m_SubscriptionsUpdateTimer->cancel ();
m_SubscriptionsUpdateTimer = nullptr; m_SubscriptionsUpdateTimer = nullptr;
} }
bool isDownloading = m_Downloading.valid (); bool isDownloading = m_Downloading.valid ();
@ -682,7 +699,7 @@ namespace client
auto dest = i2p::client::context.GetSharedLocalDestination (); auto dest = i2p::client::context.GetSharedLocalDestination ();
if (dest) if (dest)
{ {
m_SubscriptionsUpdateTimer = new boost::asio::deadline_timer (dest->GetService ()); m_SubscriptionsUpdateTimer = std::make_unique<boost::asio::deadline_timer>(dest->GetService ());
m_SubscriptionsUpdateTimer->expires_from_now (boost::posix_time::minutes(INITIAL_SUBSCRIPTION_UPDATE_TIMEOUT)); m_SubscriptionsUpdateTimer->expires_from_now (boost::posix_time::minutes(INITIAL_SUBSCRIPTION_UPDATE_TIMEOUT));
m_SubscriptionsUpdateTimer->async_wait (std::bind (&AddressBook::HandleSubscriptionsUpdateTimer, m_SubscriptionsUpdateTimer->async_wait (std::bind (&AddressBook::HandleSubscriptionsUpdateTimer,
this, std::placeholders::_1)); this, std::placeholders::_1));

View File

@ -62,7 +62,7 @@ namespace client
typedef std::map<std::string, std::shared_ptr<Address>, std::less<> > Addresses; typedef std::map<std::string, std::shared_ptr<Address>, std::less<> > Addresses;
virtual ~AddressBookStorage () {}; virtual ~AddressBookStorage () {};
virtual std::shared_ptr<const i2p::data::IdentityEx> GetAddress (const i2p::data::IdentHash& ident) const = 0; virtual std::shared_ptr<const i2p::data::IdentityEx> GetAddress (const i2p::data::IdentHash& ident) = 0;
virtual void AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address) = 0; virtual void AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address) = 0;
virtual void RemoveAddress (const i2p::data::IdentHash& ident) = 0; virtual void RemoveAddress (const i2p::data::IdentHash& ident) = 0;
@ -133,7 +133,7 @@ namespace client
int m_NumRetries; int m_NumRetries;
std::vector<std::shared_ptr<AddressBookSubscription> > m_Subscriptions; std::vector<std::shared_ptr<AddressBookSubscription> > m_Subscriptions;
std::shared_ptr<AddressBookSubscription> m_DefaultSubscription; // in case if we don't know any addresses yet std::shared_ptr<AddressBookSubscription> m_DefaultSubscription; // in case if we don't know any addresses yet
boost::asio::deadline_timer * m_SubscriptionsUpdateTimer; std::unique_ptr<boost::asio::deadline_timer> m_SubscriptionsUpdateTimer;
bool m_IsEnabled; bool m_IsEnabled;
}; };