Unverified Commit 200dce59 authored by anonimal's avatar anonimal

Instance: core API hooks

- Refactor Instance API for external API usage (won't build externally without this refactor)
- Implement Status to Instance API
- Instance: API: return uptime in plain seconds
parent ece38d7b
......@@ -38,6 +38,9 @@
#include "client/instance.h"
#include "core/instance.h"
#include "core/util/config.h"
namespace kovri
{
namespace app
......
......@@ -37,6 +37,7 @@
#include <stdexcept>
#include "client/context.h"
#include "client/util/config.h"
#include "core/router/transports/impl.h"
#include "core/util/log.h"
......@@ -50,9 +51,9 @@ namespace client
/// @notes Initializing the member with class name was/is a hack until our logger is improved
core::Exception Instance::m_Exception("Instance");
Instance::Instance(const core::Instance& core) try
: m_Core(core),
m_Config(m_Core.GetConfig()),
Instance::Instance(const core::Instance& core)
try : m_Core(std::make_shared<core::Instance>(core)),
m_Config(std::make_shared<Configuration>(m_Core->GetConfig())),
m_IsReloading(false)
{
}
......@@ -61,14 +62,12 @@ catch (...)
m_Exception.Dispatch();
}
Instance::~Instance() {}
// Note: we'd love Instance RAII but singleton needs to be daemonized (if applicable) before initialization
// TODO(unassigned): see TODO's for client context and singleton
void Instance::Initialize()
{
// Initialize core
m_Core.Initialize();
m_Core->Initialize();
LOG(debug) << "Instance: initializing client";
// TODO(unassigned): a useful shutdown handler but needs to callback to daemon
......@@ -82,7 +81,7 @@ void Instance::Initialize()
// Initialize proxies
std::shared_ptr<ClientDestination> local_destination;
auto const& map = m_Config.GetCoreConfig().GetMap();
auto const& map = m_Config->GetCoreConfig().GetMap();
auto const proxy_keys = map["proxykeys"].as<std::string>();
if (!proxy_keys.empty())
......@@ -121,13 +120,13 @@ void Instance::SetupTunnels()
// Count number of tunnels
std::size_t client_count{}, server_count{};
// Iterate through each section in tunnels config
for (auto const& tunnel : m_Config.GetParsedTunnelsConfig())
for (auto const& tunnel : m_Config->GetParsedTunnelsConfig())
{
try
{
// Test which type of tunnel (client or server)
if (tunnel.type == m_Config.GetAttribute(Key::Client)
|| tunnel.type == m_Config.GetAttribute(Key::IRC))
if (tunnel.type == m_Config->GetAttribute(Key::Client)
|| tunnel.type == m_Config->GetAttribute(Key::IRC))
{ // TODO(unassigned): see #9
if (m_IsReloading)
{
......@@ -160,7 +159,7 @@ void Instance::SetupTunnels()
else
{ // TODO(unassigned): currently, anything that's not client
bool const is_http =
(tunnel.type == m_Config.GetAttribute(Key::HTTP));
(tunnel.type == m_Config->GetAttribute(Key::HTTP));
if (m_IsReloading)
{
context.UpdateServerTunnel(tunnel, is_http);
......@@ -219,7 +218,7 @@ void Instance::Start()
try
{
LOG(debug) << "Instance: starting core";
m_Core.Start();
m_Core->Start();
// Reseed
if (core::netdb.GetNumRouters() < core::NetDb::Size::MinRequiredRouters)
......@@ -256,7 +255,7 @@ void Instance::Stop()
context.Stop();
LOG(debug) << "Instance: stopping core";
m_Core.Stop();
m_Core->Stop();
}
catch (...)
{
......@@ -273,7 +272,7 @@ void Instance::Reload()
// TODO(unassigned): locking etc.
// TODO(unassigned): core instance
m_IsReloading = true;
m_Config.ParseConfig();
m_Config->ParseConfig();
SetupTunnels();
m_IsReloading = false;
}
......
......@@ -31,16 +31,19 @@
#ifndef SRC_CLIENT_INSTANCE_H_
#define SRC_CLIENT_INSTANCE_H_
#include <memory>
#include <string>
#include <vector>
#include "client/util/config.h"
#include "core/instance.h"
namespace kovri
{
namespace client
{
// TODO(unassigned): properly remove the need to forward declare for external API usage
class Configuration;
// TODO(anonimal): we currently want to limit core interaction through client only for all apps and most API cases.
// A member function getter can return the object which will (should) change mutable data via the core API.
// In essence, the core and client Instance objects are essentially a preliminary API.
......@@ -53,12 +56,16 @@ namespace client
class Instance
{
public:
// TODO(anonimal): upon further API development, we'll most likely want non-const reference
explicit Instance(const core::Instance& core);
~Instance() = default;
Instance(const Instance&) = default;
Instance& operator=(const Instance&) = default;
// TODO(anonimal): overload ctor
~Instance();
Instance(Instance&&) = default;
Instance& operator=(Instance&&) = default;
public:
/// @brief Initializes the router's client context object
/// @details Creates tunnels, proxies and I2PControl service
void Initialize();
......@@ -77,7 +84,14 @@ class Instance
/// @return Reference to configuration object
const Configuration& GetConfig() const noexcept
{
return m_Config;
return *m_Config;
}
/// @brief Core lib (router) status accessor
/// @notes Currently only a core lib status accessor
const std::shared_ptr<core::Instance::Status>& GetStatus() const
{
return m_Core->GetStatus();
}
private:
......@@ -96,12 +110,12 @@ class Instance
/// @brief Exception dispatcher
static core::Exception m_Exception;
/// @brief Core instance
core::Instance m_Core;
/// @brief Core instance (router)
std::shared_ptr<core::Instance> m_Core;
/// @brief Client configuration implementation
/// @note Must be initialized with core configuration
Configuration m_Config;
std::shared_ptr<Configuration> m_Config;
/// @brief Is client configuration in the process of reloading?
/// TODO(unassigned): expand types of reloading
......
......@@ -44,6 +44,7 @@
#include "core/router/transports/impl.h"
#include "core/router/tunnel/impl.h"
#include "core/util/config.h"
#include "core/util/log.h"
#include "version.h"
......@@ -57,11 +58,17 @@ namespace core
/// @notes Initializing the member with class name was/is a hack until our logger is improved
core::Exception Instance::m_Exception("Instance");
Instance::Instance(const std::vector<std::string>& args) try : m_Config(args)
std::atomic<bool> Instance::m_IsRunning{false};
Instance::Instance(const std::vector<std::string>& args)
try : m_Config(std::make_shared<core::Configuration>(args)),
m_Status(std::make_shared<Instance::Status>())
{
m_IsRunning.store(false);
// TODO(anonimal): Initializing of sources/streams/sinks must come after we've properly configured the logger.
// we do this here so we can catch debug logging before instance "initialization". This is not ideal
core::SetupLogging(m_Config.GetMap());
core::SetupLogging(m_Config->GetMap());
// Log the banner
LOG(info) << "The Kovri I2P Router Project";
......@@ -73,7 +80,7 @@ Instance::Instance(const std::vector<std::string>& args) try : m_Config(args)
LOG(debug) << __func__ << ": arg=" << arg;
// Continue with configuration/setup
m_Config.SetupAESNI();
m_Config->SetupAESNI();
}
catch (const boost::program_options::error_with_option_name& ex)
{
......@@ -84,14 +91,12 @@ catch (...)
m_Exception.Dispatch();
}
Instance::~Instance() {}
// Note: we'd love Instance RAII but singleton needs to be daemonized (if applicable) before initialization
void Instance::Initialize()
{
LOG(debug) << "Instance: initializing core";
// TODO(unassigned): see TODOs for router context and singleton
context.Initialize(m_Config.GetMap());
context.Initialize(m_Config->GetMap());
}
void Instance::Start()
......@@ -110,6 +115,7 @@ void Instance::Start()
}
LOG(info) << "Instance: core successfully started";
m_IsRunning.store(true);
}
void Instance::Stop()
......@@ -128,11 +134,84 @@ void Instance::Stop()
catch (...)
{
m_Exception.Dispatch(__func__);
m_IsRunning.store(false);
throw;
}
LOG(info) << "Instance: core successfully stopped";
m_IsRunning.store(false);
}
bool Instance::Status::IsRunning() const
{
return Instance::m_IsRunning.load();
}
std::size_t Instance::Status::GetRouterTunnelsCreationRate() const
{
// TODO(unassigned): refactor rate type (should never be signed)
return static_cast<std::size_t>(core::tunnels.GetTunnelCreationSuccessRate());
}
std::size_t Instance::Status::GetActiveRouterTunnelsCount() const
{
return core::tunnels.GetTransitTunnels().size();
}
std::size_t Instance::Status::GetActivePeersCount() const
{
return core::transports.GetPeers().size();
}
std::size_t Instance::Status::GetFloodfillsCount() const
{
return core::netdb.GetNumFloodfills();
};
std::size_t Instance::Status::GetKnownPeersCount() const
{
return core::netdb.GetNumRouters();
}
std::size_t Instance::Status::GetLeaseSetsCount() const
{
return core::netdb.GetNumLeaseSets();
}
std::string Instance::Status::GetDataPath() const
{
return core::GetPath(core::Path::Core).string();
}
std::string Instance::Status::GetState() const
{
return core::context.GetState(core::context.GetState());
}
std::string Instance::Status::GetVersion() const
{
static std::string version(
std::string(KOVRI_VERSION) + "-" + KOVRI_GIT_REVISION + "-"
+ KOVRI_CODENAME);
return version;
}
std::uint32_t Instance::Status::GetInBandwidth() const
{
return core::transports.GetInBandwidth();
}
std::uint32_t Instance::Status::GetOutBandwidth() const
{
return core::transports.GetOutBandwidth();
}
std::uint64_t Instance::Status::GetUptime() const
{
return core::context.GetUptime();
}
// TODO: ib/ob tunnels
} // namespace core
} // namespace kovri
......@@ -31,22 +31,25 @@
#ifndef SRC_CORE_INSTANCE_H_
#define SRC_CORE_INSTANCE_H_
#include <atomic>
#include <memory>
#include <string>
#include <vector>
#include "core/util/config.h"
#include "core/util/exception.h"
#if defined(WITH_INTEGRATION_TESTS)
#include "core/router/net_db/impl.h"
#include "core/router/tunnel/impl.h"
#include "core/router/transports/impl.h"
#endif
namespace kovri
{
namespace core
{
// TODO(unassigned): properly remove the need to forward declare for external API usage
class Configuration;
class Exception;
/// @class Instance
/// @brief Core instance implementation
class Instance
......@@ -55,8 +58,13 @@ class Instance
/// @param args argc + argv style options
explicit Instance(
const std::vector<std::string>& args = std::vector<std::string>());
~Instance() = default;
Instance(const Instance&) = default;
Instance& operator=(const Instance&) = default;
~Instance();
Instance(Instance&&) = default;
Instance& operator=(Instance&&) = default;
/// @brief Initializes router context / core settings
void Initialize();
......@@ -71,7 +79,7 @@ class Instance
/// @return Reference to configuration object
const Configuration& GetConfig() const noexcept
{
return m_Config;
return *m_Config;
}
#if defined(WITH_INTEGRATION_TESTS)
......@@ -81,12 +89,46 @@ class Instance
}
#endif
struct Status
{
Status() = default;
~Status() = default;
bool IsRunning() const;
std::size_t GetActivePeersCount() const;
std::size_t GetActiveRouterTunnelsCount() const;
std::size_t GetFloodfillsCount() const;
std::size_t GetKnownPeersCount() const;
std::size_t GetLeaseSetsCount() const;
std::size_t GetRouterTunnelsCreationRate() const;
std::string GetDataPath() const;
std::string GetState() const;
std::string GetVersion() const;
std::uint32_t GetInBandwidth() const;
std::uint32_t GetOutBandwidth() const;
std::uint64_t GetUptime() const;
// TODO(unassigned): ib/ob tunnel lists
};
/// @brief Router status accessor
const std::shared_ptr<Status>& GetStatus() const
{
return m_Status;
};
private:
/// @brief Exception dispatcher
static core::Exception m_Exception;
static Exception m_Exception;
/// @brief Client configuration implementation
Configuration m_Config;
std::shared_ptr<Configuration> m_Config;
/// @brief Router status facade
std::shared_ptr<Status> m_Status;
/// @brief Is Instance running?
static std::atomic<bool> m_IsRunning;
};
} // namespace core
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment