Remove beast::SharedData

This commit is contained in:
Nik Bougalis
2015-10-10 19:34:59 -07:00
parent 0e7c8ce554
commit b7c3b96516
11 changed files with 413 additions and 859 deletions

View File

@@ -957,8 +957,6 @@
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\beast\beast\threads\semaphore.h"> <ClInclude Include="..\..\src\beast\beast\threads\semaphore.h">
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\beast\beast\threads\SharedData.h">
</ClInclude>
<ClInclude Include="..\..\src\beast\beast\threads\SharedLockGuard.h"> <ClInclude Include="..\..\src\beast\beast\threads\SharedLockGuard.h">
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\beast\beast\threads\SharedMutexAdapter.h"> <ClInclude Include="..\..\src\beast\beast\threads\SharedMutexAdapter.h">

View File

@@ -1596,9 +1596,6 @@
<ClInclude Include="..\..\src\beast\beast\threads\semaphore.h"> <ClInclude Include="..\..\src\beast\beast\threads\semaphore.h">
<Filter>beast\threads</Filter> <Filter>beast\threads</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\beast\beast\threads\SharedData.h">
<Filter>beast\threads</Filter>
</ClInclude>
<ClInclude Include="..\..\src\beast\beast\threads\SharedLockGuard.h"> <ClInclude Include="..\..\src\beast\beast\threads\SharedLockGuard.h">
<Filter>beast\threads</Filter> <Filter>beast\threads</Filter>
</ClInclude> </ClInclude>

View File

@@ -24,7 +24,6 @@
#include <beast/threads/TryLockGuard.h> #include <beast/threads/TryLockGuard.h>
#include <beast/threads/SharedLockGuard.h> #include <beast/threads/SharedLockGuard.h>
#include <beast/threads/SharedMutexAdapter.h> #include <beast/threads/SharedMutexAdapter.h>
#include <beast/threads/SharedData.h>
#include <beast/threads/SpinLock.h> #include <beast/threads/SpinLock.h>
#include <beast/threads/Stoppable.h> #include <beast/threads/Stoppable.h>
#include <beast/threads/Thread.h> #include <beast/threads/Thread.h>

View File

@@ -20,13 +20,13 @@
#include <beast/asio/IPAddressConversion.h> #include <beast/asio/IPAddressConversion.h>
#include <beast/asio/placeholders.h> #include <beast/asio/placeholders.h>
#include <beast/intrusive/List.h> #include <beast/intrusive/List.h>
#include <beast/threads/SharedData.h>
#include <boost/asio/ip/tcp.hpp> #include <boost/asio/ip/tcp.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <cassert> #include <cassert>
#include <climits> #include <climits>
#include <deque> #include <deque>
#include <functional> #include <functional>
#include <mutex>
#include <set> #include <set>
#include <sstream> #include <sstream>
#include <thread> #include <thread>
@@ -192,13 +192,6 @@ private:
max_packet_size = 1472 max_packet_size = 1472
}; };
struct StateType
{
List <StatsDMetricBase> metrics;
};
using State = SharedData <StateType>;
Journal m_journal; Journal m_journal;
IP::Endpoint m_address; IP::Endpoint m_address;
std::string m_prefix; std::string m_prefix;
@@ -208,7 +201,8 @@ private:
boost::asio::deadline_timer m_timer; boost::asio::deadline_timer m_timer;
boost::asio::ip::udp::socket m_socket; boost::asio::ip::udp::socket m_socket;
std::deque <std::string> m_data; std::deque <std::string> m_data;
State m_state; std::recursive_mutex metricsLock_;
List <StatsDMetricBase> metrics_;
// Must come last for order of init // Must come last for order of init
std::thread m_thread; std::thread m_thread;
@@ -288,14 +282,14 @@ public:
void add (StatsDMetricBase& metric) void add (StatsDMetricBase& metric)
{ {
State::Access state (m_state); std::lock_guard<std::recursive_mutex> _(metricsLock_);
state->metrics.push_back (metric); metrics_.push_back (metric);
} }
void remove (StatsDMetricBase& metric) void remove (StatsDMetricBase& metric)
{ {
State::Access state (m_state); std::lock_guard<std::recursive_mutex> _(metricsLock_);
state->metrics.erase (state->metrics.iterator_to (metric)); metrics_.erase (metrics_.iterator_to (metric));
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@@ -425,11 +419,10 @@ public:
return; return;
} }
State::Access state (m_state); std::lock_guard<std::recursive_mutex> _(metricsLock_);
for (List <StatsDMetricBase>::iterator iter (state->metrics.begin()); for (auto& m : metrics_)
iter != state->metrics.end(); ++iter) m.do_process();
iter->do_process();
send_buffers (); send_buffers ();

View File

@@ -1,287 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_THREADS_SHAREDDATA_H_INCLUDED
#define BEAST_THREADS_SHAREDDATA_H_INCLUDED
#include <beast/threads/RecursiveMutex.h>
#include <beast/threads/SharedMutexAdapter.h>
namespace beast {
/** Structured, multi-threaded access to a shared state.
This container combines locking semantics with data access semantics to
create an alternative to the typical synchronization method of first
acquiring a lock and then accessing data members.
With this container, access to the underlying data is only possible after
first acquiring a lock. The steps of acquiring the lock and obtaining
a const or non-const reference to the data are combined into one
RAII style operation.
There are three types of access:
- Access
Provides access to the shared state via a non-const reference or pointer.
Access acquires a unique lock on the mutex associated with the
container.
- ConstAccess
Provides access to the shared state via a const reference or pointer.
ConstAccess acquires a shared lock on the mutex associated with the
container.
- ConstUnlockedAccess
Provides access to the shared state via a const reference or pointer.
No locking is performed. It is the callers responsibility to ensure that
the operation is synchronized. This can be useful for diagnostics or
assertions, or for when it is known that no other threads can access
the data.
- UnlockedAccess
Provides access to the shared state via a reference or pointer.
No locking is performed. It is the callers responsibility to ensure that
the operation is synchronized. This can be useful for diagnostics or
assertions, or for when it is known that no other threads can access
the data.
Usage example:
@code
struct State
{
int value1;
String value2;
};
using SharedState = SharedData <State>;
SharedState m_state;
void readExample ()
{
SharedState::ConstAccess state (m_state);
print (state->value1); // read access
print (state->value2); // read access
state->value1 = 42; // write disallowed: compile error
}
void writeExample ()
{
SharedState::Access state (m_state);
state->value2 = "Label"; // write access, allowed
}
@endcode
Requirements for Value:
Constructible
Destructible
Requirements for SharedMutexType:
X is SharedMutexType, a is an instance of X:
X a; DefaultConstructible
X::LockGuardType Names a type that implements the LockGuard concept.
X::SharedLockGuardType Names a type that implements the SharedLockGuard concept.
@tparam Value The type which the container holds.
@tparam SharedMutexType The type of shared mutex to use.
*/
template <typename Value, class SharedMutexType =
SharedMutexAdapter <RecursiveMutex> >
class SharedData
{
private:
using LockGuardType = typename SharedMutexType::LockGuardType;
using SharedLockGuardType = typename SharedMutexType::SharedLockGuardType;
public:
using ValueType = Value;
class Access;
class ConstAccess;
class UnlockedAccess;
class ConstUnlockedAccess;
/** Create a shared data container.
Up to 8 parameters can be specified in the constructor. These parameters
are forwarded to the corresponding constructor in Data. If no
constructor in Data matches the parameter list, a compile error is
generated.
*/
/** @{ */
SharedData () = default;
template <class T1>
explicit SharedData (T1 t1)
: m_value (t1) { }
template <class T1, class T2>
SharedData (T1 t1, T2 t2)
: m_value (t1, t2) { }
template <class T1, class T2, class T3>
SharedData (T1 t1, T2 t2, T3 t3)
: m_value (t1, t2, t3) { }
template <class T1, class T2, class T3, class T4>
SharedData (T1 t1, T2 t2, T3 t3, T4 t4)
: m_value (t1, t2, t3, t4) { }
template <class T1, class T2, class T3, class T4, class T5>
SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
: m_value (t1, t2, t3, t4, t5) { }
template <class T1, class T2, class T3, class T4, class T5, class T6>
SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
: m_value (t1, t2, t3, t4, t5, t6) { }
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) : m_value (t1, t2, t3, t4, t5, t6, t7) { }
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
: m_value (t1, t2, t3, t4, t5, t6, t7, t8) { }
/** @} */
SharedData (SharedData const&) = delete;
SharedData& operator= (SharedData const&) = delete;
private:
Value m_value;
SharedMutexType m_mutex;
};
//------------------------------------------------------------------------------
/** Provides non-const access to the contents of a SharedData.
This acquires a unique lock on the underlying mutex.
*/
template <class Data, class SharedMutexType>
class SharedData <Data, SharedMutexType>::Access
{
public:
explicit Access (SharedData& state)
: m_state (state)
, m_lock (m_state.m_mutex)
{ }
Access (Access const&) = delete;
Access& operator= (Access const&) = delete;
Data const& get () const { return m_state.m_value; }
Data const& operator* () const { return get (); }
Data const* operator-> () const { return &get (); }
Data& get () { return m_state.m_value; }
Data& operator* () { return get (); }
Data* operator-> () { return &get (); }
private:
SharedData& m_state;
typename SharedData::LockGuardType m_lock;
};
//------------------------------------------------------------------------------
/** Provides const access to the contents of a SharedData.
This acquires a shared lock on the underlying mutex.
*/
template <class Data, class SharedMutexType>
class SharedData <Data, SharedMutexType>::ConstAccess
{
public:
/** Create a ConstAccess from the specified SharedData */
explicit ConstAccess (SharedData const volatile& state)
: m_state (const_cast <SharedData const&> (state))
, m_lock (m_state.m_mutex)
{ }
ConstAccess (ConstAccess const&) = delete;
ConstAccess& operator= (ConstAccess const&) = delete;
Data const& get () const { return m_state.m_value; }
Data const& operator* () const { return get (); }
Data const* operator-> () const { return &get (); }
private:
SharedData const& m_state;
typename SharedData::SharedLockGuardType m_lock;
};
//------------------------------------------------------------------------------
/** Provides const access to the contents of a SharedData.
This acquires a shared lock on the underlying mutex.
*/
template <class Data, class SharedMutexType>
class SharedData <Data, SharedMutexType>::ConstUnlockedAccess
{
public:
/** Create an UnlockedAccess from the specified SharedData */
explicit ConstUnlockedAccess (SharedData const volatile& state)
: m_state (const_cast <SharedData const&> (state))
{ }
ConstUnlockedAccess (ConstUnlockedAccess const&) = delete;
ConstUnlockedAccess& operator= (ConstUnlockedAccess const&) = delete;
Data const& get () const { return m_state.m_value; }
Data const& operator* () const { return get (); }
Data const* operator-> () const { return &get (); }
private:
SharedData const& m_state;
};
//------------------------------------------------------------------------------
/** Provides access to the contents of a SharedData.
This acquires a shared lock on the underlying mutex.
*/
template <class Data, class SharedMutexType>
class SharedData <Data, SharedMutexType>::UnlockedAccess
{
public:
/** Create an UnlockedAccess from the specified SharedData */
explicit UnlockedAccess (SharedData& state)
: m_state (state)
{ }
UnlockedAccess (UnlockedAccess const&) = delete;
UnlockedAccess& operator= (UnlockedAccess const&) = delete;
Data const& get () const { return m_state.m_value; }
Data const& operator* () const { return get (); }
Data const* operator-> () const { return &get (); }
Data& get () { return m_state.m_value; }
Data& operator* () { return get (); }
Data* operator-> () { return &get (); }
private:
SharedData& m_state;
};
}
#endif

View File

@@ -21,9 +21,9 @@
#define BEAST_UTILITY_PROPERTYSTREAM_H_INCLUDED #define BEAST_UTILITY_PROPERTYSTREAM_H_INCLUDED
#include <beast/intrusive/List.h> #include <beast/intrusive/List.h>
#include <beast/threads/SharedData.h>
#include <cstdint> #include <cstdint>
#include <mutex>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <utility> #include <utility>
@@ -274,31 +274,11 @@ public:
class PropertyStream::Source class PropertyStream::Source
{ {
private: private:
struct State
{
explicit State (Source* source)
: item (source)
, parent (nullptr)
{ }
Item item;
Source* parent;
List <Item> children;
};
using SharedState = SharedData <State>;
std::string const m_name; std::string const m_name;
SharedState m_state; std::recursive_mutex lock_;
Item item_;
//-------------------------------------------------------------------------- Source* parent_;
List <Item> children_;
void remove (SharedState::Access& state,
SharedState::Access& childState);
void removeAll (SharedState::Access& state);
void write (SharedState::Access& state, PropertyStream& stream);
public: public:
explicit Source (std::string const& name); explicit Source (std::string const& name);
@@ -326,7 +306,7 @@ public:
/** Remove a child source from this Source. */ /** Remove a child source from this Source. */
void remove (Source& child); void remove (Source& child);
/** Remove all child sources of this Source. */ /** Remove all child sources from this Source. */
void removeAll (); void removeAll ();
/** Write only this Source to the stream. */ /** Write only this Source to the stream. */

View File

@@ -173,16 +173,17 @@ PropertyStream const& PropertyStream::Set::stream() const
PropertyStream::Source::Source (std::string const& name) PropertyStream::Source::Source (std::string const& name)
: m_name (name) : m_name (name)
, m_state (this) , item_ (this)
, parent_ (nullptr)
{ {
} }
PropertyStream::Source::~Source () PropertyStream::Source::~Source ()
{ {
SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
if (state->parent != nullptr) if (parent_ != nullptr)
state->parent->remove (*this); parent_->remove (*this);
removeAll (state); removeAll ();
} }
std::string const& PropertyStream::Source::name () const std::string const& PropertyStream::Source::name () const
@@ -192,37 +193,35 @@ std::string const& PropertyStream::Source::name () const
void PropertyStream::Source::add (Source& source) void PropertyStream::Source::add (Source& source)
{ {
SharedState::Access state (m_state); std::lock(lock_, source.lock_);
SharedState::Access childState (source.m_state); std::lock_guard<std::recursive_mutex> lk1(lock_, std::adopt_lock);
bassert (childState->parent == nullptr); std::lock_guard<std::recursive_mutex> lk2(source.lock_, std::adopt_lock);
state->children.push_back (childState->item);
childState->parent = this; bassert (source.parent_ == nullptr);
children_.push_back (source.item_);
source.parent_ = this;
} }
void PropertyStream::Source::remove (Source& child) void PropertyStream::Source::remove (Source& child)
{ {
SharedState::Access state (m_state); std::lock(lock_, child.lock_);
SharedState::Access childState (child.m_state); std::lock_guard<std::recursive_mutex> lk1(lock_, std::adopt_lock);
remove (state, childState); std::lock_guard<std::recursive_mutex> lk2(child.lock_, std::adopt_lock);
bassert (child.parent_ == this);
children_.erase (
children_.iterator_to (
child.item_));
child.parent_ = nullptr;
} }
void PropertyStream::Source::removeAll () void PropertyStream::Source::removeAll ()
{ {
SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
removeAll (state); for (auto iter = children_.begin(); iter != children_.end(); )
}
//------------------------------------------------------------------------------
void PropertyStream::Source::write (
SharedState::Access& state, PropertyStream &stream)
{ {
for (List <Item>::iterator iter (state->children.begin()); std::lock_guard<std::recursive_mutex> _cl((*iter)->lock_);
iter != state->children.end(); ++iter) remove (*(*iter));
{
Source& source (iter->source());
Map map (source.name(), stream);
source.write (stream);
} }
} }
@@ -239,14 +238,10 @@ void PropertyStream::Source::write (PropertyStream& stream)
Map map (m_name, stream); Map map (m_name, stream);
onWrite (map); onWrite (map);
SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
for (List <Item>::iterator iter (state->children.begin()); for (auto& child : children_)
iter != state->children.end(); ++iter) child.source().write (stream);
{
Source& source (iter->source());
source.write (stream);
}
} }
void PropertyStream::Source::write (PropertyStream& stream, std::string const& path) void PropertyStream::Source::write (PropertyStream& stream, std::string const& path)
@@ -330,8 +325,9 @@ PropertyStream::Source* PropertyStream::Source::find_one_deep (std::string const
Source* found = find_one (name); Source* found = find_one (name);
if (found != nullptr) if (found != nullptr)
return found; return found;
SharedState::Access state (this->m_state);
for (auto& s : state->children) std::lock_guard<std::recursive_mutex> _(lock_);
for (auto& s : children_)
{ {
found = s.source().find_one_deep (name); found = s.source().find_one_deep (name);
if (found != nullptr) if (found != nullptr)
@@ -360,8 +356,8 @@ PropertyStream::Source* PropertyStream::Source::find_path (std::string path)
// If no immediate children match, then return nullptr // If no immediate children match, then return nullptr
PropertyStream::Source* PropertyStream::Source::find_one (std::string const& name) PropertyStream::Source* PropertyStream::Source::find_one (std::string const& name)
{ {
SharedState::Access state (this->m_state); std::lock_guard<std::recursive_mutex> _(lock_);
for (auto& s : state->children) for (auto& s : children_)
{ {
if (s.source().m_name == name) if (s.source().m_name == name)
return &s.source(); return &s.source();
@@ -373,28 +369,6 @@ void PropertyStream::Source::onWrite (Map&)
{ {
} }
//------------------------------------------------------------------------------
void PropertyStream::Source::remove (
SharedState::Access& state, SharedState::Access& childState)
{
bassert (childState->parent == this);
state->children.erase (
state->children.iterator_to (
childState->item));
childState->parent = nullptr;
}
void PropertyStream::Source::removeAll (SharedState::Access& state)
{
for (List <Item>::iterator iter (state->children.begin());
iter != state->children.end();)
{
SharedState::Access childState ((*iter)->m_state);
remove (state, childState);
}
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// //
// PropertyStream // PropertyStream

View File

@@ -29,6 +29,7 @@
#include <ripple/protocol/RippleLedgerHash.h> #include <ripple/protocol/RippleLedgerHash.h>
#include <beast/threads/Thread.h> #include <beast/threads/Thread.h>
#include <beast/cxx14/memory.h> // <memory> #include <beast/cxx14/memory.h> // <memory>
#include <mutex>
#include <thread> #include <thread>
namespace ripple { namespace ripple {
@@ -52,38 +53,24 @@ class LedgerCleanerImp
, public beast::Thread , public beast::Thread
{ {
public: public:
struct State Application& app_;
{ beast::Journal m_journal;
State() std::mutex lock_;
: minRange (0)
, maxRange (0)
, checkNodes (false)
, fixTxns (false)
, failures (0)
{
}
// The lowest ledger in the range we're checking. // The lowest ledger in the range we're checking.
LedgerIndex minRange; LedgerIndex minRange_ = 0;
// The highest ledger in the range we're checking // The highest ledger in the range we're checking
LedgerIndex maxRange; LedgerIndex maxRange_ = 0;
// Check all state/transaction nodes // Check all state/transaction nodes
bool checkNodes; bool checkNodes_ = false;
// Rewrite SQL databases // Rewrite SQL databases
bool fixTxns; bool fixTxns_ = false;
// Number of errors encountered since last success // Number of errors encountered since last success
int failures; int failures_ = 0;
};
using SharedState = beast::SharedData <State>;
Application& app_;
SharedState m_state;
beast::Journal m_journal;
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@@ -133,19 +120,19 @@ public:
void onWrite (beast::PropertyStream::Map& map) void onWrite (beast::PropertyStream::Map& map)
{ {
SharedState::Access state (m_state); std::lock_guard<std::mutex> _(lock_);
if (state->maxRange == 0) if (maxRange_ == 0)
map["status"] = "idle"; map["status"] = "idle";
else else
{ {
map["status"] = "running"; map["status"] = "running";
map["min_ledger"] = state->minRange; map["min_ledger"] = minRange_;
map["max_ledger"] = state->maxRange; map["max_ledger"] = maxRange_;
map["check_nodes"] = state->checkNodes ? "true" : "false"; map["check_nodes"] = checkNodes_ ? "true" : "false";
map["fix_txns"] = state->fixTxns ? "true" : "false"; map["fix_txns"] = fixTxns_ ? "true" : "false";
if (state->failures > 0) if (failures_ > 0)
map["fail_counts"] = state->failures; map["fail_counts"] = failures_;
} }
} }
@@ -162,13 +149,13 @@ public:
app_.getLedgerMaster().getFullValidatedRange (minRange, maxRange); app_.getLedgerMaster().getFullValidatedRange (minRange, maxRange);
{ {
SharedState::Access state (m_state); std::lock_guard<std::mutex> _(lock_);
state->maxRange = maxRange; maxRange_ = maxRange;
state->minRange = minRange; minRange_ = minRange;
state->checkNodes = false; checkNodes_ = false;
state->fixTxns = false; fixTxns_ = false;
state->failures = 0; failures_ = 0;
/* /*
JSON Parameters: JSON Parameters:
@@ -203,29 +190,29 @@ public:
// Quick way to fix a single ledger // Quick way to fix a single ledger
if (params.isMember(jss::ledger)) if (params.isMember(jss::ledger))
{ {
state->maxRange = params[jss::ledger].asUInt(); maxRange_ = params[jss::ledger].asUInt();
state->minRange = params[jss::ledger].asUInt(); minRange_ = params[jss::ledger].asUInt();
state->fixTxns = true; fixTxns_ = true;
state->checkNodes = true; checkNodes_ = true;
} }
if (params.isMember(jss::max_ledger)) if (params.isMember(jss::max_ledger))
state->maxRange = params[jss::max_ledger].asUInt(); maxRange_ = params[jss::max_ledger].asUInt();
if (params.isMember(jss::min_ledger)) if (params.isMember(jss::min_ledger))
state->minRange = params[jss::min_ledger].asUInt(); minRange_ = params[jss::min_ledger].asUInt();
if (params.isMember(jss::full)) if (params.isMember(jss::full))
state->fixTxns = state->checkNodes = params[jss::full].asBool(); fixTxns_ = checkNodes_ = params[jss::full].asBool();
if (params.isMember(jss::fix_txns)) if (params.isMember(jss::fix_txns))
state->fixTxns = params[jss::fix_txns].asBool(); fixTxns_ = params[jss::fix_txns].asBool();
if (params.isMember(jss::check_nodes)) if (params.isMember(jss::check_nodes))
state->checkNodes = params[jss::check_nodes].asBool(); checkNodes_ = params[jss::check_nodes].asBool();
if (params.isMember(jss::stop) && params[jss::stop].asBool()) if (params.isMember(jss::stop) && params[jss::stop].asBool())
state->minRange = state->maxRange = 0; minRange_ = maxRange_ = 0;
} }
notify(); notify();
@@ -411,16 +398,16 @@ public:
} }
{ {
SharedState::Access state (m_state); std::lock_guard<std::mutex> _(lock_);
if ((state->minRange > state->maxRange) || if ((minRange_ > maxRange_) ||
(state->maxRange == 0) || (state->minRange == 0)) (maxRange_ == 0) || (minRange_ == 0))
{ {
state->minRange = state->maxRange = 0; minRange_ = maxRange_ = 0;
return; return;
} }
ledgerIndex = state->maxRange; ledgerIndex = maxRange_;
doNodes = state->checkNodes; doNodes = checkNodes_;
doTxns = state->fixTxns; doTxns = fixTxns_;
} }
ledgerHash = getHash(ledgerIndex, goodLedger); ledgerHash = getHash(ledgerIndex, goodLedger);
@@ -441,8 +428,8 @@ public:
if (fail) if (fail)
{ {
{ {
SharedState::Access state (m_state); std::lock_guard<std::mutex> _(lock_);
++state->failures; ++failures_;
} }
// Wait for acquiring to catch up to us // Wait for acquiring to catch up to us
std::this_thread::sleep_for(std::chrono::seconds(2)); std::this_thread::sleep_for(std::chrono::seconds(2));
@@ -450,12 +437,12 @@ public:
else else
{ {
{ {
SharedState::Access state (m_state); std::lock_guard<std::mutex> _(lock_);
if (ledgerIndex == state->minRange) if (ledgerIndex == minRange_)
++state->minRange; ++minRange_;
if (ledgerIndex == state->maxRange) if (ledgerIndex == maxRange_)
--state->maxRange; --maxRange_;
state->failures = 0; failures_ = 0;
} }
// Reduce I/O pressure and wait for acquiring to catch up to us // Reduce I/O pressure and wait for acquiring to catch up to us
std::this_thread::sleep_for(std::chrono::milliseconds(100)); std::this_thread::sleep_for(std::chrono::milliseconds(100));

View File

@@ -55,71 +55,45 @@ public:
using Slots = std::map <beast::IP::Endpoint, using Slots = std::map <beast::IP::Endpoint,
std::shared_ptr <SlotImp>>; std::shared_ptr <SlotImp>>;
using FixedSlots = std::map <beast::IP::Endpoint, Fixed>; beast::Journal m_journal;
clock_type& m_clock;
Store& m_store;
Checker& m_checker;
// A set of unique Ripple public keys std::recursive_mutex lock_;
using Keys = std::set <RipplePublicKey>;
// A set of non-unique IPAddresses without ports, used
// to filter duplicates when making outgoing connections.
using ConnectedAddresses = std::multiset <beast::IP::Address>;
struct State
{
State (
Store* store,
clock_type& clock,
beast::Journal journal)
: stopping (false)
, counts ()
, livecache (clock, beast::Journal (
journal, Reporting::livecache))
, bootcache (*store, clock, beast::Journal (
journal, Reporting::bootcache))
{
}
// True if we are stopping. // True if we are stopping.
bool stopping; bool stopping_ = false;
// The source we are currently fetching. // The source we are currently fetching.
// This is used to cancel I/O during program exit. // This is used to cancel I/O during program exit.
beast::SharedPtr <Source> fetchSource; beast::SharedPtr <Source> fetchSource_;
// Configuration settings // Configuration settings
Config config; Config config_;
// Slot counts and other aggregate statistics. // Slot counts and other aggregate statistics.
Counts counts; Counts counts_;
// A list of slots that should always be connected // A list of slots that should always be connected
FixedSlots fixed; std::map <beast::IP::Endpoint, Fixed> fixed_;
// Live livecache from mtENDPOINTS messages // Live livecache from mtENDPOINTS messages
Livecache <> livecache; Livecache <> livecache_;
// LiveCache of addresses suitable for gaining initial connections // LiveCache of addresses suitable for gaining initial connections
Bootcache bootcache; Bootcache bootcache_;
// Holds all counts // Holds all counts
Slots slots; Slots slots_;
// The addresses (but not port) we are connected to. This includes // The addresses (but not port) we are connected to. This includes
// outgoing connection attempts. Note that this set can contain // outgoing connection attempts. Note that this set can contain
// duplicates (since the port is not set) // duplicates (since the port is not set)
ConnectedAddresses connected_addresses; std::multiset <beast::IP::Address> connectedAddresses_;
// Set of public keys belonging to active peers // Set of public keys belonging to active peers
Keys keys; std::set <RipplePublicKey> keys_;
};
using SharedState = beast::SharedData <State>;
beast::Journal m_journal;
SharedState m_state;
clock_type& m_clock;
Store& m_store;
Checker& m_checker;
// A list of dynamic sources to consult as a fallback // A list of dynamic sources to consult as a fallback
std::vector <beast::SharedPtr <Source>> m_sources; std::vector <beast::SharedPtr <Source>> m_sources;
@@ -133,10 +107,13 @@ public:
Logic (clock_type& clock, Store& store, Logic (clock_type& clock, Store& store,
Checker& checker, beast::Journal journal) Checker& checker, beast::Journal journal)
: m_journal (journal, Reporting::logic) : m_journal (journal, Reporting::logic)
, m_state (&store, std::ref (clock), journal)
, m_clock (clock) , m_clock (clock)
, m_store (store) , m_store (store)
, m_checker (checker) , m_checker (checker)
, livecache_ (m_clock,
beast::Journal (journal, Reporting::livecache))
, bootcache_ (store, m_clock,
beast::Journal (journal, Reporting::bootcache))
, m_whenBroadcast (m_clock.now()) , m_whenBroadcast (m_clock.now())
, m_squelches (m_clock) , m_squelches (m_clock)
{ {
@@ -147,9 +124,8 @@ public:
// //
void load () void load ()
{ {
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
bootcache_.load ();
state->bootcache.load ();
} }
/** Stop the logic. /** Stop the logic.
@@ -160,10 +136,10 @@ public:
*/ */
void stop () void stop ()
{ {
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
state->stopping = true; stopping_ = true;
if (state->fetchSource != nullptr) if (fetchSource_ != nullptr)
state->fetchSource->cancel (); fetchSource_->cancel ();
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@@ -175,16 +151,16 @@ public:
void void
config (Config const& c) config (Config const& c)
{ {
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
state->config = c; config_ = c;
state->counts.onConfig (state->config); counts_.onConfig (config_);
} }
Config Config
config() config()
{ {
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
return state->config; return config_;
} }
void void
@@ -200,7 +176,7 @@ public:
addFixedPeer (std::string const& name, addFixedPeer (std::string const& name,
std::vector <beast::IP::Endpoint> const& addresses) std::vector <beast::IP::Endpoint> const& addresses)
{ {
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
if (addresses.empty ()) if (addresses.empty ())
{ {
@@ -217,7 +193,7 @@ public:
remote_address.to_string ()); remote_address.to_string ());
} }
auto result (state->fixed.emplace (std::piecewise_construct, auto result (fixed_.emplace (std::piecewise_construct,
std::forward_as_tuple (remote_address), std::forward_as_tuple (remote_address),
std::make_tuple (std::ref (m_clock)))); std::make_tuple (std::ref (m_clock))));
@@ -241,9 +217,9 @@ public:
if (ec == boost::asio::error::operation_aborted) if (ec == boost::asio::error::operation_aborted)
return; return;
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
Slots::iterator const iter (state->slots.find (remoteAddress)); auto const iter (slots_.find (remoteAddress));
if (iter == state->slots.end()) if (iter == slots_.end())
{ {
// The slot disconnected before we finished the check // The slot disconnected before we finished the check
if (m_journal.debug) m_journal.debug << beast::leftw (18) << if (m_journal.debug) m_journal.debug << beast::leftw (18) <<
@@ -263,7 +239,7 @@ public:
if (m_journal.error) m_journal.error << beast::leftw (18) << if (m_journal.error) m_journal.error << beast::leftw (18) <<
"Logic testing " << iter->first << " with error, " << "Logic testing " << iter->first << " with error, " <<
ec.message(); ec.message();
state->bootcache.on_failure (checkedAddress); bootcache_.on_failure (checkedAddress);
return; return;
} }
@@ -282,14 +258,14 @@ public:
"Logic accept" << remote_endpoint << "Logic accept" << remote_endpoint <<
" on local " << local_endpoint; " on local " << local_endpoint;
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
// Check for duplicate connection // Check for duplicate connection
if (is_public (remote_endpoint)) if (is_public (remote_endpoint))
{ {
auto const iter = state->connected_addresses.find ( auto const iter = connectedAddresses_.find (
remote_endpoint.address()); remote_endpoint.address());
if (iter != state->connected_addresses.end()) if (iter != connectedAddresses_.end())
{ {
if (m_journal.debug) m_journal.debug << beast::leftw (18) << if (m_journal.debug) m_journal.debug << beast::leftw (18) <<
"Logic dropping inbound " << remote_endpoint << "Logic dropping inbound " << remote_endpoint <<
@@ -300,18 +276,18 @@ public:
// Create the slot // Create the slot
SlotImp::ptr const slot (std::make_shared <SlotImp> (local_endpoint, SlotImp::ptr const slot (std::make_shared <SlotImp> (local_endpoint,
remote_endpoint, fixed (remote_endpoint.address (), state), remote_endpoint, fixed (remote_endpoint.address ()),
m_clock)); m_clock));
// Add slot to table // Add slot to table
auto const result (state->slots.emplace ( auto const result (slots_.emplace (
slot->remote_endpoint (), slot)); slot->remote_endpoint (), slot));
// Remote address must not already exist // Remote address must not already exist
assert (result.second); assert (result.second);
// Add to the connected address list // Add to the connected address list
state->connected_addresses.emplace (remote_endpoint.address()); connectedAddresses_.emplace (remote_endpoint.address());
// Update counts // Update counts
state->counts.add (*slot); counts_.add (*slot);
return result.first->second; return result.first->second;
} }
@@ -323,11 +299,11 @@ public:
if (m_journal.debug) m_journal.debug << beast::leftw (18) << if (m_journal.debug) m_journal.debug << beast::leftw (18) <<
"Logic connect " << remote_endpoint; "Logic connect " << remote_endpoint;
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
// Check for duplicate connection // Check for duplicate connection
if (state->slots.find (remote_endpoint) != if (slots_.find (remote_endpoint) !=
state->slots.end ()) slots_.end ())
{ {
if (m_journal.debug) m_journal.debug << beast::leftw (18) << if (m_journal.debug) m_journal.debug << beast::leftw (18) <<
"Logic dropping " << remote_endpoint << "Logic dropping " << remote_endpoint <<
@@ -337,20 +313,20 @@ public:
// Create the slot // Create the slot
SlotImp::ptr const slot (std::make_shared <SlotImp> ( SlotImp::ptr const slot (std::make_shared <SlotImp> (
remote_endpoint, fixed (remote_endpoint, state), m_clock)); remote_endpoint, fixed (remote_endpoint), m_clock));
// Add slot to table // Add slot to table
std::pair <Slots::iterator, bool> result ( auto const result =
state->slots.emplace (slot->remote_endpoint (), slots_.emplace (slot->remote_endpoint (),
slot)); slot);
// Remote address must not already exist // Remote address must not already exist
assert (result.second); assert (result.second);
// Add to the connected address list // Add to the connected address list
state->connected_addresses.emplace (remote_endpoint.address()); connectedAddresses_.emplace (remote_endpoint.address());
// Update counts // Update counts
state->counts.add (*slot); counts_.add (*slot);
return result.first->second; return result.first->second;
} }
@@ -363,18 +339,18 @@ public:
"Logic connected" << slot->remote_endpoint () << "Logic connected" << slot->remote_endpoint () <<
" on local " << local_endpoint; " on local " << local_endpoint;
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
// The object must exist in our table // The object must exist in our table
assert (state->slots.find (slot->remote_endpoint ()) != assert (slots_.find (slot->remote_endpoint ()) !=
state->slots.end ()); slots_.end ());
// Assign the local endpoint now that it's known // Assign the local endpoint now that it's known
slot->local_endpoint (local_endpoint); slot->local_endpoint (local_endpoint);
// Check for self-connect by address // Check for self-connect by address
{ {
auto const iter (state->slots.find (local_endpoint)); auto const iter (slots_.find (local_endpoint));
if (iter != state->slots.end ()) if (iter != slots_.end ())
{ {
assert (iter->second->local_endpoint () assert (iter->second->local_endpoint ()
== slot->remote_endpoint ()); == slot->remote_endpoint ());
@@ -386,9 +362,9 @@ public:
} }
// Update counts // Update counts
state->counts.remove (*slot); counts_.remove (*slot);
slot->state (Slot::connected); slot->state (Slot::connected);
state->counts.add (*slot); counts_.add (*slot);
return true; return true;
} }
@@ -400,56 +376,55 @@ public:
"Logic handshake " << slot->remote_endpoint () << "Logic handshake " << slot->remote_endpoint () <<
" with " << (cluster ? "clustered " : "") << "key " << key; " with " << (cluster ? "clustered " : "") << "key " << key;
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
// The object must exist in our table // The object must exist in our table
assert (state->slots.find (slot->remote_endpoint ()) != assert (slots_.find (slot->remote_endpoint ()) !=
state->slots.end ()); slots_.end ());
// Must be accepted or connected // Must be accepted or connected
assert (slot->state() == Slot::accept || assert (slot->state() == Slot::accept ||
slot->state() == Slot::connected); slot->state() == Slot::connected);
// Check for duplicate connection by key // Check for duplicate connection by key
if (state->keys.find (key) != state->keys.end()) if (keys_.find (key) != keys_.end())
return Result::duplicate; return Result::duplicate;
// See if we have an open space for this slot // See if we have an open space for this slot
if (! state->counts.can_activate (*slot)) if (! counts_.can_activate (*slot))
{ {
if (! slot->inbound()) if (! slot->inbound())
state->bootcache.on_success ( bootcache_.on_success (
slot->remote_endpoint()); slot->remote_endpoint());
return Result::full; return Result::full;
} }
// Set key and cluster right before adding to the map // Set key and cluster right before adding to the map
// otherwise we could assert later when erasing the key. // otherwise we could assert later when erasing the key.
state->counts.remove (*slot); counts_.remove (*slot);
slot->public_key (key); slot->public_key (key);
slot->cluster (cluster); slot->cluster (cluster);
state->counts.add (*slot); counts_.add (*slot);
// Add the public key to the active set // Add the public key to the active set
std::pair <Keys::iterator, bool> const result ( auto const result = keys_.insert (key);
state->keys.insert (key));
// Public key must not already exist // Public key must not already exist
assert (result.second); assert (result.second);
(void) result.second; (void) result.second;
// Change state and update counts // Change state and update counts
state->counts.remove (*slot); counts_.remove (*slot);
slot->activate (m_clock.now ()); slot->activate (m_clock.now ());
state->counts.add (*slot); counts_.add (*slot);
if (! slot->inbound()) if (! slot->inbound())
state->bootcache.on_success ( bootcache_.on_success (
slot->remote_endpoint()); slot->remote_endpoint());
// Mark fixed slot success // Mark fixed slot success
if (slot->fixed() && ! slot->inbound()) if (slot->fixed() && ! slot->inbound())
{ {
auto iter (state->fixed.find (slot->remote_endpoint())); auto iter (fixed_.find (slot->remote_endpoint()));
assert (iter != state->fixed.end ()); assert (iter != fixed_.end ());
iter->second.success (m_clock.now ()); iter->second.success (m_clock.now ());
if (m_journal.trace) m_journal.trace << beast::leftw (18) << if (m_journal.trace) m_journal.trace << beast::leftw (18) <<
"Logic fixed " << slot->remote_endpoint () << " success"; "Logic fixed " << slot->remote_endpoint () << " success";
@@ -465,12 +440,12 @@ public:
std::vector <Endpoint> std::vector <Endpoint>
redirect (SlotImp::ptr const& slot) redirect (SlotImp::ptr const& slot)
{ {
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
RedirectHandouts h (slot); RedirectHandouts h (slot);
state->livecache.hops.shuffle(); livecache_.hops.shuffle();
handout (&h, (&h)+1, handout (&h, (&h)+1,
state->livecache.hops.begin(), livecache_.hops.begin(),
state->livecache.hops.end()); livecache_.hops.end());
return std::move(h.list()); return std::move(h.list());
} }
@@ -485,27 +460,33 @@ public:
{ {
std::vector <beast::IP::Endpoint> const none; std::vector <beast::IP::Endpoint> const none;
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
// Count how many more outbound attempts to make // Count how many more outbound attempts to make
// //
auto needed (state->counts.attempts_needed ()); auto needed (counts_.attempts_needed ());
if (needed == 0) if (needed == 0)
return none; return none;
ConnectHandouts h (needed, m_squelches); ConnectHandouts h (needed, m_squelches);
// Make sure we don't connect to already-connected entries. // Make sure we don't connect to already-connected entries.
squelch_slots (state); for (auto const& s : slots_)
{
auto const result (m_squelches.insert (
s.second->remote_endpoint().address()));
if (! result.second)
m_squelches.touch (result.first);
}
// 1. Use Fixed if: // 1. Use Fixed if:
// Fixed active count is below fixed count AND // Fixed active count is below fixed count AND
// ( There are eligible fixed addresses to try OR // ( There are eligible fixed addresses to try OR
// Any outbound attempts are in progress) // Any outbound attempts are in progress)
// //
if (state->counts.fixed_active() < state->fixed.size ()) if (counts_.fixed_active() < fixed_.size ())
{ {
get_fixed (needed, h.list(), m_squelches, state); get_fixed (needed, h.list(), m_squelches);
if (! h.list().empty ()) if (! h.list().empty ())
{ {
@@ -514,11 +495,11 @@ public:
return h.list(); return h.list();
} }
if (state->counts.attempts() > 0) if (counts_.attempts() > 0)
{ {
if (m_journal.debug) m_journal.debug << beast::leftw (18) << if (m_journal.debug) m_journal.debug << beast::leftw (18) <<
"Logic waiting on " << "Logic waiting on " <<
state->counts.attempts() << " attempts"; counts_.attempts() << " attempts";
return none; return none;
} }
} }
@@ -526,8 +507,8 @@ public:
// Only proceed if auto connect is enabled and we // Only proceed if auto connect is enabled and we
// have less than the desired number of outbound slots // have less than the desired number of outbound slots
// //
if (! state->config.autoConnect || if (! config_.autoConnect ||
state->counts.out_active () >= state->counts.out_max ()) counts_.out_active () >= counts_.out_max ())
return none; return none;
// 2. Use Livecache if: // 2. Use Livecache if:
@@ -535,10 +516,10 @@ public:
// Any outbound attempts are in progress // Any outbound attempts are in progress
// //
{ {
state->livecache.hops.shuffle(); livecache_.hops.shuffle();
handout (&h, (&h)+1, handout (&h, (&h)+1,
state->livecache.hops.rbegin(), livecache_.hops.rbegin(),
state->livecache.hops.rend()); livecache_.hops.rend());
if (! h.list().empty ()) if (! h.list().empty ())
{ {
if (m_journal.debug) m_journal.debug << beast::leftw (18) << if (m_journal.debug) m_journal.debug << beast::leftw (18) <<
@@ -546,11 +527,11 @@ public:
((h.list().size () > 1) ? "endpoints" : "endpoint"); ((h.list().size () > 1) ? "endpoints" : "endpoint");
return h.list(); return h.list();
} }
else if (state->counts.attempts() > 0) else if (counts_.attempts() > 0)
{ {
if (m_journal.debug) m_journal.debug << beast::leftw (18) << if (m_journal.debug) m_journal.debug << beast::leftw (18) <<
"Logic waiting on " << "Logic waiting on " <<
state->counts.attempts() << " attempts"; counts_.attempts() << " attempts";
return none; return none;
} }
} }
@@ -571,8 +552,8 @@ public:
// 4. Use Bootcache if: // 4. Use Bootcache if:
// There are any entries we haven't tried lately // There are any entries we haven't tried lately
// //
for (auto iter (state->bootcache.begin()); for (auto iter (bootcache_.begin());
! h.full() && iter != state->bootcache.end(); ++iter) ! h.full() && iter != bootcache_.end(); ++iter)
h.try_insert (*iter); h.try_insert (*iter);
if (! h.list().empty ()) if (! h.list().empty ())
@@ -592,7 +573,7 @@ public:
{ {
std::vector<std::pair<Slot::ptr, std::vector<Endpoint>>> result; std::vector<std::pair<Slot::ptr, std::vector<Endpoint>>> result;
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
clock_type::time_point const now = m_clock.now(); clock_type::time_point const now = m_clock.now();
if (m_whenBroadcast <= now) if (m_whenBroadcast <= now)
@@ -602,8 +583,8 @@ public:
{ {
// build list of active slots // build list of active slots
std::vector <SlotImp::ptr> slots; std::vector <SlotImp::ptr> slots;
slots.reserve (state->slots.size()); slots.reserve (slots_.size());
std::for_each (state->slots.cbegin(), state->slots.cend(), std::for_each (slots_.cbegin(), slots_.cend(),
[&slots](Slots::value_type const& value) [&slots](Slots::value_type const& value)
{ {
if (value.second->state() == Slot::active) if (value.second->state() == Slot::active)
@@ -632,23 +613,23 @@ public:
// 2. We have slots // 2. We have slots
// 3. We haven't failed the firewalled test // 3. We haven't failed the firewalled test
// //
if (state->config.wantIncoming && if (config_.wantIncoming &&
state->counts.inboundSlots() > 0) counts_.inboundSlots() > 0)
{ {
Endpoint ep; Endpoint ep;
ep.hops = 0; ep.hops = 0;
ep.address = beast::IP::Endpoint ( ep.address = beast::IP::Endpoint (
beast::IP::AddressV4 ()).at_port ( beast::IP::AddressV4 ()).at_port (
state->config.listeningPort); config_.listeningPort);
for (auto& t : targets) for (auto& t : targets)
t.insert (ep); t.insert (ep);
} }
// build sequence of endpoints by hops // build sequence of endpoints by hops
state->livecache.hops.shuffle(); livecache_.hops.shuffle();
handout (targets.begin(), targets.end(), handout (targets.begin(), targets.end(),
state->livecache.hops.begin(), livecache_.hops.begin(),
state->livecache.hops.end()); livecache_.hops.end());
// broadcast // broadcast
for (auto const& t : targets) for (auto const& t : targets)
@@ -670,30 +651,29 @@ public:
void once_per_second() void once_per_second()
{ {
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
// Expire the Livecache // Expire the Livecache
state->livecache.expire (); livecache_.expire ();
// Expire the recent cache in each slot // Expire the recent cache in each slot
for (auto const& entry : state->slots) for (auto const& entry : slots_)
entry.second->expire(); entry.second->expire();
// Expire the recent attempts table // Expire the recent attempts table
beast::expire (m_squelches, beast::expire (m_squelches,
Tuning::recentAttemptDuration); Tuning::recentAttemptDuration);
state->bootcache.periodicActivity (); bootcache_.periodicActivity ();
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// Validate and clean up the list that we received from the slot. // Validate and clean up the list that we received from the slot.
void preprocess (SlotImp::ptr const& slot, Endpoints& list, void preprocess (SlotImp::ptr const& slot, Endpoints& list)
typename SharedState::Access& state)
{ {
bool neighbor (false); bool neighbor (false);
for (auto iter (list.begin()); iter != list.end();) for (auto iter = list.begin(); iter != list.end();)
{ {
Endpoint& ep (*iter); Endpoint& ep (*iter);
@@ -767,16 +747,16 @@ public:
" contained " << list.size () << " contained " << list.size () <<
((list.size() > 1) ? " entries" : " entry"); ((list.size() > 1) ? " entries" : " entry");
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
// The object must exist in our table // The object must exist in our table
assert (state->slots.find (slot->remote_endpoint ()) != assert (slots_.find (slot->remote_endpoint ()) !=
state->slots.end ()); slots_.end ());
// Must be handshaked! // Must be handshaked!
assert (slot->state() == Slot::active); assert (slot->state() == Slot::active);
preprocess (slot, list, state); preprocess (slot, list);
clock_type::time_point const now (m_clock.now()); clock_type::time_point const now (m_clock.now());
@@ -827,8 +807,8 @@ public:
// listening test, else we silently drop their messsage // listening test, else we silently drop their messsage
// since their listening port is misconfigured. // since their listening port is misconfigured.
// //
state->livecache.insert (ep); livecache_.insert (ep);
state->bootcache.insert (ep.address); bootcache_.insert (ep.address);
} }
slot->whenAcceptEndpoints = now + Tuning::secondsPerMessage; slot->whenAcceptEndpoints = now + Tuning::secondsPerMessage;
@@ -839,52 +819,52 @@ public:
void on_legacy_endpoints (IPAddresses const& list) void on_legacy_endpoints (IPAddresses const& list)
{ {
// Ignoring them also seems a valid choice. // Ignoring them also seems a valid choice.
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
for (IPAddresses::const_iterator iter (list.begin()); for (IPAddresses::const_iterator iter (list.begin());
iter != list.end(); ++iter) iter != list.end(); ++iter)
state->bootcache.insert (*iter); bootcache_.insert (*iter);
} }
void remove (SlotImp::ptr const& slot, typename SharedState::Access& state) void remove (SlotImp::ptr const& slot)
{ {
Slots::iterator const iter (state->slots.find ( auto const iter = slots_.find (
slot->remote_endpoint ())); slot->remote_endpoint ());
// The slot must exist in the table // The slot must exist in the table
assert (iter != state->slots.end ()); assert (iter != slots_.end ());
// Remove from slot by IP table // Remove from slot by IP table
state->slots.erase (iter); slots_.erase (iter);
// Remove the key if present // Remove the key if present
if (slot->public_key () != boost::none) if (slot->public_key () != boost::none)
{ {
Keys::iterator const iter (state->keys.find (*slot->public_key())); auto const iter = keys_.find (*slot->public_key());
// Key must exist // Key must exist
assert (iter != state->keys.end ()); assert (iter != keys_.end ());
state->keys.erase (iter); keys_.erase (iter);
} }
// Remove from connected address table // Remove from connected address table
{ {
auto const iter (state->connected_addresses.find ( auto const iter (connectedAddresses_.find (
slot->remote_endpoint().address())); slot->remote_endpoint().address()));
// Address must exist // Address must exist
assert (iter != state->connected_addresses.end ()); assert (iter != connectedAddresses_.end ());
state->connected_addresses.erase (iter); connectedAddresses_.erase (iter);
} }
// Update counts // Update counts
state->counts.remove (*slot); counts_.remove (*slot);
} }
void on_closed (SlotImp::ptr const& slot) void on_closed (SlotImp::ptr const& slot)
{ {
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
remove (slot, state); remove (slot);
// Mark fixed slot failure // Mark fixed slot failure
if (slot->fixed() && ! slot->inbound() && slot->state() != Slot::active) if (slot->fixed() && ! slot->inbound() && slot->state() != Slot::active)
{ {
auto iter (state->fixed.find (slot->remote_endpoint())); auto iter (fixed_.find (slot->remote_endpoint()));
assert (iter != state->fixed.end ()); assert (iter != fixed_.end ());
iter->second.failure (m_clock.now ()); iter->second.failure (m_clock.now ());
if (m_journal.debug) m_journal.debug << beast::leftw (18) << if (m_journal.debug) m_journal.debug << beast::leftw (18) <<
"Logic fixed " << slot->remote_endpoint () << " failed"; "Logic fixed " << slot->remote_endpoint () << " failed";
@@ -900,7 +880,7 @@ public:
case Slot::connect: case Slot::connect:
case Slot::connected: case Slot::connected:
state->bootcache.on_failure (slot->remote_endpoint ()); bootcache_.on_failure (slot->remote_endpoint ());
// VFALCO TODO If the address exists in the ephemeral/live // VFALCO TODO If the address exists in the ephemeral/live
// endpoint livecache then we should mark the failure // endpoint livecache then we should mark the failure
// as if it didn't pass the listening test. We should also // as if it didn't pass the listening test. We should also
@@ -925,9 +905,9 @@ public:
void on_failure (SlotImp::ptr const& slot) void on_failure (SlotImp::ptr const& slot)
{ {
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
state->bootcache.on_failure (slot->remote_endpoint ()); bootcache_.on_failure (slot->remote_endpoint ());
} }
// Insert a set of redirect IP addresses into the Bootcache // Insert a set of redirect IP addresses into the Bootcache
@@ -939,9 +919,10 @@ public:
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// Returns `true` if the address matches a fixed slot address // Returns `true` if the address matches a fixed slot address
bool fixed (beast::IP::Endpoint const& endpoint, typename SharedState::Access& state) const // Must have the lock held
bool fixed (beast::IP::Endpoint const& endpoint) const
{ {
for (auto const& entry : state->fixed) for (auto const& entry : fixed_)
if (entry.first == endpoint) if (entry.first == endpoint)
return true; return true;
return false; return false;
@@ -949,9 +930,10 @@ public:
// Returns `true` if the address matches a fixed slot address // Returns `true` if the address matches a fixed slot address
// Note that this does not use the port information in the IP::Endpoint // Note that this does not use the port information in the IP::Endpoint
bool fixed (beast::IP::Address const& address, typename SharedState::Access& state) const // Must have the lock held
bool fixed (beast::IP::Address const& address) const
{ {
for (auto const& entry : state->fixed) for (auto const& entry : fixed_)
if (entry.first.address () == address) if (entry.first.address () == address)
return true; return true;
return false; return false;
@@ -966,17 +948,16 @@ public:
/** Adds eligible Fixed addresses for outbound attempts. */ /** Adds eligible Fixed addresses for outbound attempts. */
template <class Container> template <class Container>
void get_fixed (std::size_t needed, Container& c, void get_fixed (std::size_t needed, Container& c,
typename ConnectHandouts::Squelches& squelches, typename ConnectHandouts::Squelches& squelches)
typename SharedState::Access& state)
{ {
auto const now (m_clock.now()); auto const now (m_clock.now());
for (auto iter = state->fixed.begin (); for (auto iter = fixed_.begin ();
needed && iter != state->fixed.end (); ++iter) needed && iter != fixed_.end (); ++iter)
{ {
auto const& address (iter->first.address()); auto const& address (iter->first.address());
if (iter->second.when() <= now && squelches.find(address) == if (iter->second.when() <= now && squelches.find(address) ==
squelches.end() && std::none_of ( squelches.end() && std::none_of (
state->slots.cbegin(), state->slots.cend(), slots_.cbegin(), slots_.cend(),
[address](Slots::value_type const& v) [address](Slots::value_type const& v)
{ {
return address == v.first.address(); return address == v.first.address();
@@ -991,20 +972,6 @@ public:
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// Adds slot addresses to the squelched set
void squelch_slots (typename SharedState::Access& state)
{
for (auto const& s : state->slots)
{
auto const result (m_squelches.insert (
s.second->remote_endpoint().address()));
if (! result.second)
m_squelches.touch (result.first);
}
}
//--------------------------------------------------------------------------
void void
addStaticSource (beast::SharedPtr <Source> const& source) addStaticSource (beast::SharedPtr <Source> const& source)
{ {
@@ -1023,25 +990,16 @@ public:
// //
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// Add one address.
// Returns `true` if the address is new.
//
bool addBootcacheAddress (beast::IP::Endpoint const& address,
typename SharedState::Access& state)
{
return state->bootcache.insert (address);
}
// Add a set of addresses. // Add a set of addresses.
// Returns the number of addresses added. // Returns the number of addresses added.
// //
int addBootcacheAddresses (IPAddresses const& list) int addBootcacheAddresses (IPAddresses const& list)
{ {
int count (0); int count (0);
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
for (auto addr : list) for (auto addr : list)
{ {
if (addBootcacheAddress (addr, state)) if (bootcache_.insert (addr))
++count; ++count;
} }
return count; return count;
@@ -1054,10 +1012,10 @@ public:
{ {
{ {
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
if (state->stopping) if (stopping_)
return; return;
state->fetchSource = source; fetchSource_ = source;
} }
// VFALCO NOTE The fetch is synchronous, // VFALCO NOTE The fetch is synchronous,
@@ -1066,10 +1024,10 @@ public:
source->fetch (results, m_journal); source->fetch (results, m_journal);
{ {
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
if (state->stopping) if (stopping_)
return; return;
state->fetchSource = nullptr; fetchSource_ = nullptr;
} }
} }
@@ -1135,37 +1093,37 @@ public:
void onWrite (beast::PropertyStream::Map& map) void onWrite (beast::PropertyStream::Map& map)
{ {
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
// VFALCO NOTE These ugly casts are needed because // VFALCO NOTE These ugly casts are needed because
// of how std::size_t is declared on some linuxes // of how std::size_t is declared on some linuxes
// //
map ["bootcache"] = std::uint32_t (state->bootcache.size()); map ["bootcache"] = std::uint32_t (bootcache_.size());
map ["fixed"] = std::uint32_t (state->fixed.size()); map ["fixed"] = std::uint32_t (fixed_.size());
{ {
beast::PropertyStream::Set child ("peers", map); beast::PropertyStream::Set child ("peers", map);
writeSlots (child, state->slots); writeSlots (child, slots_);
} }
{ {
beast::PropertyStream::Map child ("counts", map); beast::PropertyStream::Map child ("counts", map);
state->counts.onWrite (child); counts_.onWrite (child);
} }
{ {
beast::PropertyStream::Map child ("config", map); beast::PropertyStream::Map child ("config", map);
state->config.onWrite (child); config_.onWrite (child);
} }
{ {
beast::PropertyStream::Map child ("livecache", map); beast::PropertyStream::Map child ("livecache", map);
state->livecache.onWrite (child); livecache_.onWrite (child);
} }
{ {
beast::PropertyStream::Map child ("bootcache", map); beast::PropertyStream::Map child ("bootcache", map);
state->bootcache.onWrite (child); bootcache_.onWrite (child);
} }
} }
@@ -1175,14 +1133,9 @@ public:
// //
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
State const& state () const
{
return *typename SharedState::ConstAccess (m_state);
}
Counts const& counts () const Counts const& counts () const
{ {
return typename SharedState::ConstAccess (m_state)->counts; return counts_;
} }
static std::string stateString (Slot::State state) static std::string stateString (Slot::State state)
@@ -1209,10 +1162,10 @@ void
Logic<Checker>::onRedirects (FwdIter first, FwdIter last, Logic<Checker>::onRedirects (FwdIter first, FwdIter last,
boost::asio::ip::tcp::endpoint const& remote_address) boost::asio::ip::tcp::endpoint const& remote_address)
{ {
typename SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
std::size_t n = 0; std::size_t n = 0;
for(;first != last && n < Tuning::maxRedirects; ++first, ++n) for(;first != last && n < Tuning::maxRedirects; ++first, ++n)
state->bootcache.insert( bootcache_.insert(
beast::IPAddressConversion::from_asio(*first)); beast::IPAddressConversion::from_asio(*first));
if (n > 0) if (n > 0)
if (m_journal.trace) m_journal.trace << beast::leftw (18) << if (m_journal.trace) m_journal.trace << beast::leftw (18) <<

View File

@@ -29,8 +29,8 @@
#include <ripple/protocol/JsonFields.h> #include <ripple/protocol/JsonFields.h>
#include <beast/chrono/abstract_clock.h> #include <beast/chrono/abstract_clock.h>
#include <beast/Insight.h> #include <beast/Insight.h>
#include <beast/threads/SharedData.h>
#include <beast/utility/PropertyStream.h> #include <beast/utility/PropertyStream.h>
#include <mutex>
namespace ripple { namespace ripple {
namespace Resource { namespace Resource {
@@ -43,33 +43,6 @@ private:
using Table = hash_map <Key, Entry, Key::hasher, Key::key_equal>; using Table = hash_map <Key, Entry, Key::hasher, Key::key_equal>;
using EntryIntrusiveList = beast::List <Entry>; using EntryIntrusiveList = beast::List <Entry>;
struct State
{
// Table of all entries
Table table;
// Because the following are intrusive lists, a given Entry may be in
// at most list at a given instant. The Entry must be removed from
// one list before placing it in another.
// List of all active inbound entries
EntryIntrusiveList inbound;
// List of all active outbound entries
EntryIntrusiveList outbound;
// List of all active admin entries
EntryIntrusiveList admin;
// List of all inactve entries
EntryIntrusiveList inactive;
// All imported gossip data
Imports import_table;
};
using SharedState = beast::SharedData <State>;
struct Stats struct Stats
{ {
Stats (beast::insight::Collector::ptr const& collector) Stats (beast::insight::Collector::ptr const& collector)
@@ -82,11 +55,34 @@ private:
beast::insight::Meter drop; beast::insight::Meter drop;
}; };
SharedState m_state;
Stats m_stats; Stats m_stats;
Stopwatch& m_clock; Stopwatch& m_clock;
beast::Journal m_journal; beast::Journal m_journal;
std::recursive_mutex lock_;
// Table of all entries
Table table_;
// Because the following are intrusive lists, a given Entry may be in
// at most list at a given instant. The Entry must be removed from
// one list before placing it in another.
// List of all active inbound entries
EntryIntrusiveList inbound_;
// List of all active outbound entries
EntryIntrusiveList outbound_;
// List of all active admin entries
EntryIntrusiveList admin_;
// List of all inactve entries
EntryIntrusiveList inactive_;
// All imported gossip data
Imports importTable_;
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
public: public:
@@ -105,9 +101,8 @@ public:
// Order matters here as well, the import table has to be // Order matters here as well, the import table has to be
// destroyed before the consumer table. // destroyed before the consumer table.
// //
SharedState::UnlockedAccess state (m_state); importTable_.clear();
state->import_table.clear(); table_.clear();
state->table.clear();
} }
Consumer newInboundEndpoint (beast::IP::Endpoint const& address) Consumer newInboundEndpoint (beast::IP::Endpoint const& address)
@@ -115,11 +110,11 @@ public:
Entry* entry (nullptr); Entry* entry (nullptr);
{ {
SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
std::pair <Table::iterator, bool> result ( auto result =
state->table.emplace (std::piecewise_construct, table_.emplace (std::piecewise_construct,
std::make_tuple (kindInbound, address.at_port (0)), // Key std::make_tuple (kindInbound, address.at_port (0)), // Key
std::make_tuple (m_clock.now()))); // Entry std::make_tuple (m_clock.now())); // Entry
entry = &result.first->second; entry = &result.first->second;
entry->key = &result.first->first; entry->key = &result.first->first;
@@ -128,10 +123,10 @@ public:
{ {
if (! result.second) if (! result.second)
{ {
state->inactive.erase ( inactive_.erase (
state->inactive.iterator_to (*entry)); inactive_.iterator_to (*entry));
} }
state->inbound.push_back (*entry); inbound_.push_back (*entry);
} }
} }
@@ -146,11 +141,11 @@ public:
Entry* entry (nullptr); Entry* entry (nullptr);
{ {
SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
std::pair <Table::iterator, bool> result ( auto result =
state->table.emplace (std::piecewise_construct, table_.emplace (std::piecewise_construct,
std::make_tuple (kindOutbound, address), // Key std::make_tuple (kindOutbound, address), // Key
std::make_tuple (m_clock.now()))); // Entry std::make_tuple (m_clock.now())); // Entry
entry = &result.first->second; entry = &result.first->second;
entry->key = &result.first->first; entry->key = &result.first->first;
@@ -158,9 +153,9 @@ public:
if (entry->refcount == 1) if (entry->refcount == 1)
{ {
if (! result.second) if (! result.second)
state->inactive.erase ( inactive_.erase (
state->inactive.iterator_to (*entry)); inactive_.iterator_to (*entry));
state->outbound.push_back (*entry); outbound_.push_back (*entry);
} }
} }
@@ -175,11 +170,11 @@ public:
Entry* entry (nullptr); Entry* entry (nullptr);
{ {
SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
std::pair <Table::iterator, bool> result ( auto result =
state->table.emplace (std::piecewise_construct, table_.emplace (std::piecewise_construct,
std::make_tuple (kindAdmin, name), // Key std::make_tuple (kindAdmin, name), // Key
std::make_tuple (m_clock.now()))); // Entry std::make_tuple (m_clock.now())); // Entry
entry = &result.first->second; entry = &result.first->second;
entry->key = &result.first->first; entry->key = &result.first->first;
@@ -187,9 +182,9 @@ public:
if (entry->refcount == 1) if (entry->refcount == 1)
{ {
if (! result.second) if (! result.second)
state->inactive.erase ( inactive_.erase (
state->inactive.iterator_to (*entry)); inactive_.iterator_to (*entry));
state->admin.push_back (*entry); admin_.push_back (*entry);
} }
} }
@@ -207,11 +202,11 @@ public:
Entry* entry (nullptr); Entry* entry (nullptr);
{ {
SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
std::pair <Table::iterator, bool> result ( auto result =
state->table.emplace (std::piecewise_construct, table_.emplace (std::piecewise_construct,
std::make_tuple (kindAdmin, name), // Key std::make_tuple (kindAdmin, name), // Key
std::make_tuple (m_clock.now()))); // Entry std::make_tuple (m_clock.now())); // Entry
entry = &result.first->second; entry = &result.first->second;
entry->key = &result.first->first; entry->key = &result.first->first;
@@ -219,12 +214,12 @@ public:
if (entry->refcount == 1) if (entry->refcount == 1)
{ {
if (! result.second) if (! result.second)
state->inactive.erase ( inactive_.erase (
state->inactive.iterator_to (*entry)); inactive_.iterator_to (*entry));
state->admin.push_back (*entry); admin_.push_back (*entry);
} }
release (prior, state); release (prior);
} }
return *entry; return *entry;
@@ -241,9 +236,9 @@ public:
clock_type::time_point const now (m_clock.now()); clock_type::time_point const now (m_clock.now());
Json::Value ret (Json::objectValue); Json::Value ret (Json::objectValue);
SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
for (auto& inboundEntry : state->inbound) for (auto& inboundEntry : inbound_)
{ {
int localBalance = inboundEntry.local_balance.value (now); int localBalance = inboundEntry.local_balance.value (now);
if ((localBalance + inboundEntry.remote_balance) >= threshold) if ((localBalance + inboundEntry.remote_balance) >= threshold)
@@ -255,7 +250,7 @@ public:
} }
} }
for (auto& outboundEntry : state->outbound) for (auto& outboundEntry : outbound_)
{ {
int localBalance = outboundEntry.local_balance.value (now); int localBalance = outboundEntry.local_balance.value (now);
if ((localBalance + outboundEntry.remote_balance) >= threshold) if ((localBalance + outboundEntry.remote_balance) >= threshold)
@@ -267,7 +262,7 @@ public:
} }
} }
for (auto& adminEntry : state->admin) for (auto& adminEntry : admin_)
{ {
int localBalance = adminEntry.local_balance.value (now); int localBalance = adminEntry.local_balance.value (now);
if ((localBalance + adminEntry.remote_balance) >= threshold) if ((localBalance + adminEntry.remote_balance) >= threshold)
@@ -288,11 +283,11 @@ public:
clock_type::time_point const now (m_clock.now()); clock_type::time_point const now (m_clock.now());
Gossip gossip; Gossip gossip;
SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
gossip.items.reserve (state->inbound.size()); gossip.items.reserve (inbound_.size());
for (auto& inboundEntry : state->inbound) for (auto& inboundEntry : inbound_)
{ {
Gossip::Item item; Gossip::Item item;
item.balance = inboundEntry.local_balance.value (now); item.balance = inboundEntry.local_balance.value (now);
@@ -312,11 +307,11 @@ public:
{ {
clock_type::rep const elapsed (m_clock.now().time_since_epoch().count()); clock_type::rep const elapsed (m_clock.now().time_since_epoch().count());
{ {
SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
std::pair <Imports::iterator, bool> result ( auto result =
state->import_table.emplace (std::piecewise_construct, importTable_.emplace (std::piecewise_construct,
std::make_tuple(origin), // Key std::make_tuple(origin), // Key
std::make_tuple(m_clock.now().time_since_epoch().count()))); // Import std::make_tuple(m_clock.now().time_since_epoch().count())); // Import
if (result.second) if (result.second)
{ {
@@ -368,19 +363,19 @@ public:
// //
void periodicActivity () void periodicActivity ()
{ {
SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
clock_type::rep const elapsed (m_clock.now().time_since_epoch().count()); clock_type::rep const elapsed (m_clock.now().time_since_epoch().count());
for (auto iter (state->inactive.begin()); iter != state->inactive.end();) for (auto iter (inactive_.begin()); iter != inactive_.end();)
{ {
if (iter->whenExpires <= elapsed) if (iter->whenExpires <= elapsed)
{ {
m_journal.debug << "Expired " << *iter; m_journal.debug << "Expired " << *iter;
Table::iterator table_iter ( auto table_iter =
state->table.find (*iter->key)); table_.find (*iter->key);
++iter; ++iter;
erase (table_iter, state); erase (table_iter);
} }
else else
{ {
@@ -388,8 +383,8 @@ public:
} }
} }
Imports::iterator iter (state->import_table.begin()); auto iter = importTable_.begin();
while (iter != state->import_table.end()) while (iter != importTable_.end())
{ {
Import& import (iter->second); Import& import (iter->second);
if (iter->second.whenExpires <= elapsed) if (iter->second.whenExpires <= elapsed)
@@ -400,7 +395,7 @@ public:
item_iter->consumer.entry().remote_balance -= item_iter->balance; item_iter->consumer.entry().remote_balance -= item_iter->balance;
} }
iter = state->import_table.erase (iter); iter = importTable_.erase (iter);
} }
else else
++iter; ++iter;
@@ -421,13 +416,25 @@ public:
return Disposition::ok; return Disposition::ok;
} }
void acquire (Entry& entry, SharedState::Access& state) void erase (Table::iterator iter)
{ {
std::lock_guard<std::recursive_mutex> _(lock_);
Entry& entry (iter->second);
assert (entry.refcount == 0);
inactive_.erase (
inactive_.iterator_to (entry));
table_.erase (iter);
}
void acquire (Entry& entry)
{
std::lock_guard<std::recursive_mutex> _(lock_);
++entry.refcount; ++entry.refcount;
} }
void release (Entry& entry, SharedState::Access& state) void release (Entry& entry)
{ {
std::lock_guard<std::recursive_mutex> _(lock_);
if (--entry.refcount == 0) if (--entry.refcount == 0)
{ {
m_journal.debug << m_journal.debug <<
@@ -436,37 +443,29 @@ public:
switch (entry.key->kind) switch (entry.key->kind)
{ {
case kindInbound: case kindInbound:
state->inbound.erase ( inbound_.erase (
state->inbound.iterator_to (entry)); inbound_.iterator_to (entry));
break; break;
case kindOutbound: case kindOutbound:
state->outbound.erase ( outbound_.erase (
state->outbound.iterator_to (entry)); outbound_.iterator_to (entry));
break; break;
case kindAdmin: case kindAdmin:
state->admin.erase ( admin_.erase (
state->admin.iterator_to (entry)); admin_.iterator_to (entry));
break; break;
default: default:
bassertfalse; bassertfalse;
break; break;
} }
state->inactive.push_back (entry); inactive_.push_back (entry);
entry.whenExpires = m_clock.now().time_since_epoch().count() + secondsUntilExpiration; entry.whenExpires = m_clock.now().time_since_epoch().count() + secondsUntilExpiration;
} }
} }
void erase (Table::iterator iter, SharedState::Access& state) Disposition charge (Entry& entry, Charge const& fee)
{
Entry& entry (iter->second);
bassert (entry.refcount == 0);
state->inactive.erase (
state->inactive.iterator_to (entry));
state->table.erase (iter);
}
Disposition charge (Entry& entry, Charge const& fee, SharedState::Access& state)
{ {
std::lock_guard<std::recursive_mutex> _(lock_);
clock_type::time_point const now (m_clock.now()); clock_type::time_point const now (m_clock.now());
int const balance (entry.add (fee.cost(), now)); int const balance (entry.add (fee.cost(), now));
m_journal.trace << m_journal.trace <<
@@ -474,30 +473,35 @@ public:
return disposition (balance); return disposition (balance);
} }
bool warn (Entry& entry, SharedState::Access& state) bool warn (Entry& entry)
{ {
if (entry.admin())
return false;
std::lock_guard<std::recursive_mutex> _(lock_);
bool notify (false); bool notify (false);
clock_type::rep const elapsed (m_clock.now().time_since_epoch().count()); clock_type::rep const elapsed (m_clock.now().time_since_epoch().count());
if (entry.balance (m_clock.now()) >= warningThreshold && if (entry.balance (m_clock.now()) >= warningThreshold &&
elapsed != entry.lastWarningTime) elapsed != entry.lastWarningTime)
{ {
charge (entry, feeWarning, state); charge (entry, feeWarning);
notify = true; notify = true;
entry.lastWarningTime = elapsed; entry.lastWarningTime = elapsed;
} }
if (notify) if (notify)
m_journal.info << m_journal.info <<
"Load warning: " << entry; "Load warning: " << entry;
if (notify) if (notify)
++m_stats.warn; ++m_stats.warn;
return notify; return notify;
} }
bool disconnect (Entry& entry, SharedState::Access& state) bool disconnect (Entry& entry)
{ {
if (entry.admin())
return false;
std::lock_guard<std::recursive_mutex> _(lock_);
bool drop (false); bool drop (false);
clock_type::time_point const now (m_clock.now()); clock_type::time_point const now (m_clock.now());
int const balance (entry.balance (now)); int const balance (entry.balance (now));
@@ -511,60 +515,17 @@ public:
// Adding feeDrop at this point keeps the dropped connection // Adding feeDrop at this point keeps the dropped connection
// from re-connecting for at least a little while after it is // from re-connecting for at least a little while after it is
// dropped. // dropped.
charge (entry, feeDrop, state); charge (entry, feeDrop);
++m_stats.drop; ++m_stats.drop;
drop = true; drop = true;
} }
return drop; return drop;
} }
int balance (Entry& entry, SharedState::Access& state)
{
return entry.balance (m_clock.now());
}
//--------------------------------------------------------------------------
void acquire (Entry& entry)
{
SharedState::Access state (m_state);
acquire (entry, state);
}
void release (Entry& entry)
{
SharedState::Access state (m_state);
release (entry, state);
}
Disposition charge (Entry& entry, Charge const& fee)
{
SharedState::Access state (m_state);
return charge (entry, fee, state);
}
bool warn (Entry& entry)
{
if (entry.admin())
return false;
SharedState::Access state (m_state);
return warn (entry, state);
}
bool disconnect (Entry& entry)
{
if (entry.admin())
return false;
SharedState::Access state (m_state);
return disconnect (entry, state);
}
int balance (Entry& entry) int balance (Entry& entry)
{ {
SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
return balance (entry, state); return entry.balance (m_clock.now());
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@@ -590,26 +551,26 @@ public:
{ {
clock_type::time_point const now (m_clock.now()); clock_type::time_point const now (m_clock.now());
SharedState::Access state (m_state); std::lock_guard<std::recursive_mutex> _(lock_);
{ {
beast::PropertyStream::Set s ("inbound", map); beast::PropertyStream::Set s ("inbound", map);
writeList (now, s, state->inbound); writeList (now, s, inbound_);
} }
{ {
beast::PropertyStream::Set s ("outbound", map); beast::PropertyStream::Set s ("outbound", map);
writeList (now, s, state->outbound); writeList (now, s, outbound_);
} }
{ {
beast::PropertyStream::Set s ("admin", map); beast::PropertyStream::Set s ("admin", map);
writeList (now, s, state->admin); writeList (now, s, admin_);
} }
{ {
beast::PropertyStream::Set s ("inactive", map); beast::PropertyStream::Set s ("inactive", map);
writeList (now, s, state->inactive); writeList (now, s, inactive_);
} }
} }
}; };

View File

@@ -24,7 +24,6 @@
#include <ripple/server/Handler.h> #include <ripple/server/Handler.h>
#include <ripple/server/Server.h> #include <ripple/server/Server.h>
#include <beast/intrusive/List.h> #include <beast/intrusive/List.h>
#include <beast/threads/SharedData.h>
#include <beast/threads/Thread.h> #include <beast/threads/Thread.h>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/intrusive/list.hpp> #include <boost/intrusive/list.hpp>