diff --git a/Builds/VisualStudio2012/RippleD.vcxproj b/Builds/VisualStudio2012/RippleD.vcxproj
index 833bc9e19..e34c07ff9 100644
--- a/Builds/VisualStudio2012/RippleD.vcxproj
+++ b/Builds/VisualStudio2012/RippleD.vcxproj
@@ -2192,7 +2192,6 @@
-
diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters
index f293b033e..25fa02abd 100644
--- a/Builds/VisualStudio2012/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters
@@ -2559,9 +2559,6 @@
[1] Ripple\resource\api
-
- [1] Ripple\resource\impl
-
[1] Ripple\peerfinder\impl
diff --git a/src/ripple/resource/api/Types.h b/src/ripple/resource/api/Types.h
index c788d53e3..b39ecc4a0 100644
--- a/src/ripple/resource/api/Types.h
+++ b/src/ripple/resource/api/Types.h
@@ -26,9 +26,6 @@ namespace Resource {
struct Key;
struct Entry;
-/** Measures seconds from an unspecified fixed reference event in the past. */
-typedef int DiscreteTime;
-
}
}
diff --git a/src/ripple/resource/impl/Entry.h b/src/ripple/resource/impl/Entry.h
index 7167659cf..35b3d0beb 100644
--- a/src/ripple/resource/impl/Entry.h
+++ b/src/ripple/resource/impl/Entry.h
@@ -23,6 +23,8 @@
namespace ripple {
namespace Resource {
+typedef abstract_clock clock_type;
+
// An entry in the table
struct Entry : public List ::Node
{
@@ -57,14 +59,14 @@ struct Entry : public List ::Node
}
// Balance including remote contributions
- int balance (DiscreteTime const now)
+ int balance (clock_type::rep const now)
{
return local_balance.value (now) + remote_balance;
}
// Add a charge and return normalized balance
// including contributions from imports.
- int add (int charge, DiscreteTime const now)
+ int add (int charge, clock_type::rep const now)
{
return local_balance.add (charge, now) + remote_balance;
}
@@ -85,10 +87,10 @@ struct Entry : public List ::Node
Disposition disposition;
// Time of the last warning
- DiscreteTime lastWarningTime;
+ clock_type::rep lastWarningTime;
// For inactive entries, time after which this entry will be erased
- DiscreteTime whenExpires;
+ clock_type::rep whenExpires;
};
std::ostream& operator<< (std::ostream& os, Entry const& v)
diff --git a/src/ripple/resource/impl/Import.h b/src/ripple/resource/impl/Import.h
index 43c222633..38723aa31 100644
--- a/src/ripple/resource/impl/Import.h
+++ b/src/ripple/resource/impl/Import.h
@@ -39,7 +39,7 @@ struct Import
}
// When the imported data expires
- DiscreteTime whenExpires;
+ clock_type::rep whenExpires;
// List of remote entries
std::vector - items;
diff --git a/src/ripple/resource/impl/Logic.h b/src/ripple/resource/impl/Logic.h
index 760f3afd1..d2c9e98fe 100644
--- a/src/ripple/resource/impl/Logic.h
+++ b/src/ripple/resource/impl/Logic.h
@@ -26,6 +26,7 @@ namespace Resource {
class Logic
{
public:
+ typedef abstract_clock clock_type;
typedef boost::unordered_map Imports;
typedef boost::unordered_map Table;
@@ -53,13 +54,13 @@ public:
typedef SharedData SharedState;
SharedState m_state;
- DiscreteClock m_clock;
+ abstract_clock & m_clock;
Journal m_journal;
//--------------------------------------------------------------------------
- Logic (DiscreteClock ::Source& source, Journal journal)
- : m_clock (source)
+ Logic (clock_type& clock, Journal journal)
+ : m_clock (clock)
, m_journal (journal)
{
}
@@ -212,7 +213,7 @@ public:
Json::Value getJson (int threshold)
{
- DiscreteTime const now (m_clock());
+ clock_type::rep const now (m_clock.elapsed());
Json::Value ret (Json::objectValue);
SharedState::Access state (m_state);
@@ -262,7 +263,7 @@ public:
Gossip exportConsumers ()
{
- DiscreteTime const now (m_clock());
+ clock_type::rep const now (m_clock.elapsed());
Gossip gossip;
SharedState::Access state (m_state);
@@ -288,7 +289,7 @@ public:
void importConsumers (std::string const& origin, Gossip const& gossip)
{
- DiscreteTime const now (m_clock());
+ clock_type::rep const now (m_clock.elapsed());
{
SharedState::Access state (m_state);
@@ -357,7 +358,7 @@ public:
{
SharedState::Access state (m_state);
- DiscreteTime const now (m_clock());
+ clock_type::rep const now (m_clock.elapsed());
for (List ::iterator iter (
state->inactive.begin()); iter != state->inactive.end();)
@@ -440,7 +441,7 @@ public:
break;
}
state->inactive.push_back (entry);
- entry.whenExpires = m_clock() + secondsUntilExpiration;
+ entry.whenExpires = m_clock.elapsed() + secondsUntilExpiration;
}
}
@@ -455,7 +456,7 @@ public:
Disposition charge (Entry& entry, Charge const& fee, SharedState::Access& state)
{
- DiscreteTime const now (m_clock());
+ clock_type::rep const now (m_clock.elapsed());
int const balance (entry.add (fee.cost(), now));
m_journal.info <<
"Charging " << entry << " for " << fee;
@@ -465,7 +466,7 @@ public:
bool warn (Entry& entry, SharedState::Access& state)
{
bool notify (false);
- DiscreteTime const now (m_clock());
+ clock_type::rep const now (m_clock.elapsed());
if (entry.balance (now) >= warningThreshold && now != entry.lastWarningTime)
{
charge (entry, feeWarning, state);
@@ -483,7 +484,7 @@ public:
bool disconnect (Entry& entry, SharedState::Access& state)
{
bool drop (false);
- DiscreteTime const now (m_clock());
+ clock_type::rep const now (m_clock.elapsed());
if (entry.balance (now) >= dropThreshold)
{
charge (entry, feeDrop, state);
@@ -494,7 +495,7 @@ public:
int balance (Entry& entry, SharedState::Access& state)
{
- return entry.balance (m_clock());
+ return entry.balance (m_clock.elapsed());
}
//--------------------------------------------------------------------------
@@ -544,7 +545,7 @@ public:
//--------------------------------------------------------------------------
void writeList (
- DiscreteTime const now,
+ clock_type::rep const now,
PropertyStream::Set& items,
List & list)
{
@@ -563,7 +564,7 @@ public:
void onWrite (PropertyStream::Map& map)
{
- DiscreteTime const now (m_clock());
+ clock_type::rep const now (m_clock.elapsed());
SharedState::Access state (m_state);
diff --git a/src/ripple/resource/impl/LogicType.h b/src/ripple/resource/impl/LogicType.h
deleted file mode 100644
index e33d9862b..000000000
--- a/src/ripple/resource/impl/LogicType.h
+++ /dev/null
@@ -1,48 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- This file is part of rippled: https://github.com/ripple/rippled
- Copyright (c) 2012, 2013 Ripple Labs Inc.
-
- 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 RIPPLE_RESOURCE_LOGICTYPE_H_INCLUDED
-#define RIPPLE_RESOURCE_LOGICTYPE_H_INCLUDED
-
-namespace ripple {
-namespace Resource {
-
-template
-class LogicType
- : private BaseFromMember
- , public Logic
-{
-public:
- typedef typename DiscreteClockSourceType::DiscreteClockType DiscreteClockType;
-
- explicit LogicType (Journal journal)
- : Logic (BaseFromMember ::member(), journal)
- {
- }
-
- DiscreteClockSourceType& clock()
- {
- return BaseFromMember ::member();
- }
-};
-
-}
-}
-
-#endif
diff --git a/src/ripple/resource/impl/Manager.cpp b/src/ripple/resource/impl/Manager.cpp
index 509122e65..0d7fff470 100644
--- a/src/ripple/resource/impl/Manager.cpp
+++ b/src/ripple/resource/impl/Manager.cpp
@@ -26,12 +26,13 @@ class ManagerImp
{
public:
Journal m_journal;
- LogicType m_logic;
+ Logic m_logic;
ManagerImp (Journal journal)
: Thread ("Resource::Manager")
, m_journal (journal)
- , m_logic (journal)
+ , m_logic (get_abstract_clock <
+ std::chrono::steady_clock, std::chrono::seconds> (), journal)
{
startThread ();
}
diff --git a/src/ripple/resource/impl/Tests.cpp b/src/ripple/resource/impl/Tests.cpp
index cced99d0a..a7a1f40f8 100644
--- a/src/ripple/resource/impl/Tests.cpp
+++ b/src/ripple/resource/impl/Tests.cpp
@@ -23,6 +23,34 @@ namespace Resource {
class Tests : public UnitTest
{
public:
+ class TestLogic
+ : private boost::base_from_member >
+ , public Logic
+
+ {
+ private:
+ typedef boost::base_from_member <
+ manual_clock > clock_type;
+
+ public:
+ explicit TestLogic (Journal journal)
+ : Logic (member, journal)
+ {
+ }
+
+ void advance ()
+ {
+ ++member;
+ }
+
+ manual_clock & clock ()
+ {
+ return member;
+ }
+ };
+
+ //--------------------------------------------------------------------------
+
void createGossip (Gossip& gossip)
{
int const v (10 + random().nextInt (10));
@@ -38,11 +66,89 @@ public:
}
}
- void testImports ()
+ //--------------------------------------------------------------------------
+
+ enum
+ {
+ maxLoopCount = 10000
+ };
+
+ void testDrop (Journal j)
+ {
+ beginTestCase ("Warn/drop");
+
+ Tests::TestLogic logic (j);
+
+ Charge const fee (dropThreshold + 1);
+ IPAddress const addr (
+ IPAddress::from_string ("207.127.82.2"));
+
+ {
+ Consumer c (logic.newInboundEndpoint (addr));
+
+ // Create load until we get a warning
+ for (std::size_t n (maxLoopCount); n>=0; --n)
+ {
+ if (n == 0)
+ {
+ fail ("Loop count exceeded without warning");
+ return;
+ }
+
+ if (c.charge (fee) == warn)
+ {
+ pass ();
+ break;
+ }
+ ++logic.clock ();
+ }
+
+ // Create load until we get dropped
+ for (std::size_t n (maxLoopCount); n>=0; --n)
+ {
+ if (n == 0)
+ {
+ fail ("Loop count exceeded without dropping");
+ return;
+ }
+
+ if (c.charge (fee) == drop)
+ {
+ pass ();
+ break;
+ }
+ ++logic.clock ();
+ }
+
+ }
+
+ {
+ Consumer c (logic.newInboundEndpoint (addr));
+ expect (c.disconnect ());
+ }
+
+ for (std::size_t n (maxLoopCount); n>=0; --n)
+ {
+ Consumer c (logic.newInboundEndpoint (addr));
+ if (n == 0)
+ {
+ fail ("Loop count exceeded without expiring black list");
+ return;
+ }
+
+ if (c.disposition() != drop)
+ {
+ pass ();
+ break;
+ }
+ }
+ }
+
+ void testImports (Journal j)
{
beginTestCase ("Imports");
- LogicType logic (journal());
+ TestLogic logic (j);
Gossip g[5];
@@ -55,11 +161,11 @@ public:
pass();
}
- void testImport ()
+ void testImport (Journal j)
{
beginTestCase ("Import");
- LogicType logic (journal());
+ TestLogic logic (j);
Gossip g;
Gossip::Item item;
@@ -72,37 +178,41 @@ public:
pass();
}
- void testCharges ()
+ void testCharges (Journal j)
{
beginTestCase ("Charge");
- LogicType logic (journal());
+ TestLogic logic (j);
{
IPAddress address (IPAddress::from_string ("207.127.82.1"));
Consumer c (logic.newInboundEndpoint (address));
- logMessage ("Charging " + c.to_string() + " 10,000 units");
- c.charge (10000);
+ Charge fee (1000);
+ j.info <<
+ "Charging " << c.to_string() << " " << fee << " per second";
+ c.charge (fee);
for (int i = 0; i < 128; ++i)
{
- logMessage (
- "Time = " + String::fromNumber (logic.clock().now()) +
- ", Balance = " + String::fromNumber (c.balance()));
- ++logic.clock().now();
+ j.info <<
+ "Time= " << logic.clock().now().time_since_epoch() <<
+ ", Balance = " << c.balance();
+ logic.advance();
}
}
{
IPAddress address (IPAddress::from_string ("207.127.82.2"));
Consumer c (logic.newInboundEndpoint (address));
- logMessage ("Charging " + c.to_string() + " 1000 units per second");
+ Charge fee (1000);
+ j.info <<
+ "Charging " << c.to_string() << " " << fee << " per second";
for (int i = 0; i < 128; ++i)
{
- c.charge (1000);
- logMessage (
- "Time = " + String::fromNumber (logic.clock().now()) +
- ", Balance = " + String::fromNumber (c.balance()));
- ++logic.clock().now();
+ c.charge (fee);
+ j.info <<
+ "Time= " << logic.clock().now().time_since_epoch() <<
+ ", Balance = " << c.balance();
+ logic.advance();
}
}
@@ -111,12 +221,16 @@ public:
void runTest ()
{
- testCharges();
- testImports();
- testImport();
+ //Journal j (journal());
+ Journal j;
+
+ testDrop (j);
+ testCharges (j);
+ testImports (j);
+ testImport (j);
}
- Tests () : UnitTest ("ResourceManager", "ripple", runManual)
+ Tests () : UnitTest ("ResourceManager", "ripple")
{
}
};
diff --git a/src/ripple/resource/ripple_resource.cpp b/src/ripple/resource/ripple_resource.cpp
index ac5c57ede..62db919d2 100644
--- a/src/ripple/resource/ripple_resource.cpp
+++ b/src/ripple/resource/ripple_resource.cpp
@@ -22,9 +22,9 @@
#include "ripple_resource.h"
#include "../algorithm/api/DecayingSample.h"
-#include "../algorithm/api/DiscreteClock.h"
#include "beast/modules/beast_core/system/BeforeBoost.h"
+#include
#include
#include "impl/Fees.cpp"
@@ -35,7 +35,6 @@
# include "impl/Import.h"
#include "impl/Charge.cpp"
# include "impl/Logic.h"
-# include "impl/LogicType.h"
#include "impl/Consumer.cpp"
#include "impl/LegacyFees.cpp"
#include "impl/Manager.cpp"