Browse Source

use std::async for address book download

pull/2121/head
orignal 3 weeks ago
parent
commit
0086f8e27a
  1. 37
      libi2pd_client/AddressBook.cpp
  2. 7
      libi2pd_client/AddressBook.h

37
libi2pd_client/AddressBook.cpp

@ -305,7 +305,7 @@ namespace client
identHash = hash; identHash = hash;
} }
AddressBook::AddressBook (): m_Storage(nullptr), m_IsLoaded (false), m_IsDownloading (false), AddressBook::AddressBook (): m_Storage(nullptr), m_IsLoaded (false),
m_NumRetries (0), m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr), m_NumRetries (0), m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr),
m_IsEnabled (true) m_IsEnabled (true)
{ {
@ -344,20 +344,28 @@ namespace client
delete m_SubscriptionsUpdateTimer; delete m_SubscriptionsUpdateTimer;
m_SubscriptionsUpdateTimer = nullptr; m_SubscriptionsUpdateTimer = nullptr;
} }
if (m_IsDownloading) bool isDownloading = m_Downloading.valid ();
if (isDownloading)
{
if (m_Downloading.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
isDownloading = false;
else
{ {
LogPrint (eLogInfo, "Addressbook: Subscriptions are downloading, abort"); LogPrint (eLogInfo, "Addressbook: Subscriptions are downloading, abort");
for (int i = 0; i < 30; i++) for (int i = 0; i < 30; i++)
{ {
if (!m_IsDownloading) if (m_Downloading.wait_for(std::chrono::seconds(1)) == std::future_status::ready) // wait for 1 seconds
{ {
isDownloading = false;
LogPrint (eLogInfo, "Addressbook: Subscriptions download complete"); LogPrint (eLogInfo, "Addressbook: Subscriptions download complete");
break; break;
} }
std::this_thread::sleep_for (std::chrono::seconds (1)); // wait for 1 seconds
} }
}
if (!isDownloading)
m_Downloading.get ();
else
LogPrint (eLogError, "Addressbook: Subscription download timeout"); LogPrint (eLogError, "Addressbook: Subscription download timeout");
m_IsDownloading = false;
} }
if (m_Storage) if (m_Storage)
{ {
@ -644,7 +652,6 @@ namespace client
void AddressBook::DownloadComplete (bool success, const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified) void AddressBook::DownloadComplete (bool success, const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified)
{ {
m_IsDownloading = false;
m_NumRetries++; m_NumRetries++;
int nextUpdateTimeout = m_NumRetries*CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT; int nextUpdateTimeout = m_NumRetries*CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT;
if (m_NumRetries > CONTINIOUS_SUBSCRIPTION_MAX_NUM_RETRIES || nextUpdateTimeout > CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT) if (m_NumRetries > CONTINIOUS_SUBSCRIPTION_MAX_NUM_RETRIES || nextUpdateTimeout > CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT)
@ -699,7 +706,13 @@ namespace client
LogPrint(eLogWarning, "Addressbook: Missing local destination, skip subscription update"); LogPrint(eLogWarning, "Addressbook: Missing local destination, skip subscription update");
return; return;
} }
if (!m_IsDownloading && dest->IsReady ()) bool isDownloading = m_Downloading.valid ();
if (isDownloading && m_Downloading.wait_for(std::chrono::seconds(0)) == std::future_status::ready) // still active?
{
m_Downloading.get ();
isDownloading = false;
}
if (!isDownloading && dest->IsReady ())
{ {
if (!m_IsLoaded) if (!m_IsLoaded)
{ {
@ -708,17 +721,15 @@ namespace client
std::string defaultSubURL; i2p::config::GetOption("addressbook.defaulturl", defaultSubURL); std::string defaultSubURL; i2p::config::GetOption("addressbook.defaulturl", defaultSubURL);
if (!m_DefaultSubscription) if (!m_DefaultSubscription)
m_DefaultSubscription = std::make_shared<AddressBookSubscription>(*this, defaultSubURL); m_DefaultSubscription = std::make_shared<AddressBookSubscription>(*this, defaultSubURL);
m_IsDownloading = true; m_Downloading = std::async (std::launch::async,
std::thread load_hosts(std::bind (&AddressBookSubscription::CheckUpdates, m_DefaultSubscription)); std::bind (&AddressBookSubscription::CheckUpdates, m_DefaultSubscription));
load_hosts.detach(); // TODO: use join
} }
else if (!m_Subscriptions.empty ()) else if (!m_Subscriptions.empty ())
{ {
// pick random subscription // pick random subscription
auto ind = rand () % m_Subscriptions.size(); auto ind = rand () % m_Subscriptions.size();
m_IsDownloading = true; m_Downloading = std::async (std::launch::async,
std::thread load_hosts(std::bind (&AddressBookSubscription::CheckUpdates, m_Subscriptions[ind])); std::bind (&AddressBookSubscription::CheckUpdates, m_Subscriptions[ind]));
load_hosts.detach(); // TODO: use join
} }
} }
else else

7
libi2pd_client/AddressBook.h

@ -11,10 +11,12 @@
#include <string.h> #include <string.h>
#include <string> #include <string>
#include <string_view>
#include <map> #include <map>
#include <vector> #include <vector>
#include <iostream> #include <iostream>
#include <mutex> #include <mutex>
#include <future>
#include <memory> #include <memory>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "Base.h" #include "Base.h"
@ -124,7 +126,8 @@ namespace client
std::mutex m_LookupsMutex; std::mutex m_LookupsMutex;
std::map<uint32_t, std::string> m_Lookups; // nonce -> address std::map<uint32_t, std::string> m_Lookups; // nonce -> address
AddressBookStorage * m_Storage; AddressBookStorage * m_Storage;
volatile bool m_IsLoaded, m_IsDownloading; volatile bool m_IsLoaded;
std::future<void> m_Downloading;
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
@ -136,7 +139,7 @@ namespace client
{ {
public: public:
AddressBookSubscription (AddressBook& book, const std::string& link); AddressBookSubscription (AddressBook& book, std::string_view link);
void CheckUpdates (); void CheckUpdates ();
private: private:

Loading…
Cancel
Save