Make llarp_time_t serializable in sqlite_orm

pull/1312/head
Stephen Shelton 4 years ago
parent aa1c8f257f
commit a9ce319e76
No known key found for this signature in database
GPG Key ID: EE4BADACCE8B631C

@ -29,10 +29,61 @@ namespace llarp
make_column("numDistinctRCsReceived", &PeerStats::numDistinctRCsReceived), make_column("numDistinctRCsReceived", &PeerStats::numDistinctRCsReceived),
make_column("numLateRCs", &PeerStats::numLateRCs), make_column("numLateRCs", &PeerStats::numLateRCs),
make_column("peakBandwidthBytesPerSec", &PeerStats::peakBandwidthBytesPerSec), make_column("peakBandwidthBytesPerSec", &PeerStats::peakBandwidthBytesPerSec),
make_column("longestRCReceiveIntervalMs", &PeerStats::longestRCReceiveIntervalMs), make_column("longestRCReceiveInterval", &PeerStats::longestRCReceiveInterval),
make_column("mostExpiredRCMs", &PeerStats::mostExpiredRCMs))); make_column("leastRCRemainingLifetime", &PeerStats::leastRCRemainingLifetime)));
} }
using PeerDbStorage = decltype(initStorage("")); using PeerDbStorage = decltype(initStorage(""));
} // namespace llarp } // namespace llarp
/// "custom" types for sqlite_orm
/// reference: https://github.com/fnc12/sqlite_orm/blob/master/examples/enum_binding.cpp
namespace sqlite_orm
{
template <>
struct type_printer<llarp_time_t> : public integer_printer
{
};
template <>
struct statement_binder<llarp_time_t>
{
int
bind(sqlite3_stmt* stmt, int index, const llarp_time_t& value)
{
return statement_binder<int64_t>().bind(stmt, index, value.count());
}
};
template <>
struct field_printer<llarp_time_t>
{
std::string
operator()(const llarp_time_t& value) const
{
std::stringstream stream;
stream << value.count();
return stream.str();
}
};
template <>
struct row_extractor<llarp_time_t>
{
llarp_time_t
extract(const char* row_value)
{
int64_t raw = static_cast<int64_t>(atoi(row_value));
return llarp_time_t(raw);
}
llarp_time_t
extract(sqlite3_stmt* stmt, int columnIndex)
{
auto str = sqlite3_column_text(stmt, columnIndex);
return this->extract((const char*)str);
}
};
} // namespace sqlite_orm

@ -203,7 +203,7 @@ namespace llarp
auto& stats = m_peerStats[id]; auto& stats = m_peerStats[id];
stats.routerId = id.ToString(); stats.routerId = id.ToString();
const bool isNewRC = (stats.lastRCUpdated < rc.last_updated.count()); const bool isNewRC = (stats.lastRCUpdated < rc.last_updated);
if (isNewRC) if (isNewRC)
{ {
@ -211,20 +211,20 @@ namespace llarp
if (stats.numDistinctRCsReceived > 1) if (stats.numDistinctRCsReceived > 1)
{ {
const int64_t prevRCExpiration = (stats.lastRCUpdated + RouterContact::Lifetime.count()); auto prevRCExpiration = (stats.lastRCUpdated + RouterContact::Lifetime);
// we track max expiry as the delta between (last expiration time - time received), // we track max expiry as the delta between (last expiration time - time received),
// and this value will be negative for an unhealthy router // and this value will be negative for an unhealthy router
// TODO: handle case where new RC is also expired? just ignore? // TODO: handle case where new RC is also expired? just ignore?
int64_t expiry = (prevRCExpiration - now.count()); auto expiry = prevRCExpiration - now;
if (stats.numDistinctRCsReceived == 2) if (stats.numDistinctRCsReceived == 2)
stats.mostExpiredRCMs = expiry; stats.leastRCRemainingLifetime = expiry;
else else
stats.mostExpiredRCMs = std::min(stats.mostExpiredRCMs, expiry); stats.leastRCRemainingLifetime = std::min(stats.leastRCRemainingLifetime, expiry);
} }
stats.lastRCUpdated = rc.last_updated.count(); stats.lastRCUpdated = rc.last_updated;
stats.stale = true; stats.stale = true;
} }
} }

@ -27,9 +27,8 @@ namespace llarp
numLateRCs += other.numLateRCs; numLateRCs += other.numLateRCs;
peakBandwidthBytesPerSec = std::max(peakBandwidthBytesPerSec, other.peakBandwidthBytesPerSec); peakBandwidthBytesPerSec = std::max(peakBandwidthBytesPerSec, other.peakBandwidthBytesPerSec);
longestRCReceiveIntervalMs = longestRCReceiveInterval = std::max(longestRCReceiveInterval, other.longestRCReceiveInterval);
std::max(longestRCReceiveIntervalMs, other.longestRCReceiveIntervalMs); leastRCRemainingLifetime = std::max(leastRCRemainingLifetime, other.leastRCRemainingLifetime);
mostExpiredRCMs = std::max(mostExpiredRCMs, other.mostExpiredRCMs);
lastRCUpdated = std::max(lastRCUpdated, other.lastRCUpdated); lastRCUpdated = std::max(lastRCUpdated, other.lastRCUpdated);
return *this; return *this;
@ -52,8 +51,9 @@ namespace llarp
and numLateRCs == other.numLateRCs and numLateRCs == other.numLateRCs
and peakBandwidthBytesPerSec == other.peakBandwidthBytesPerSec and peakBandwidthBytesPerSec == other.peakBandwidthBytesPerSec
and longestRCReceiveIntervalMs == other.longestRCReceiveIntervalMs and longestRCReceiveInterval == other.longestRCReceiveInterval
and mostExpiredRCMs == other.mostExpiredRCMs and lastRCUpdated == other.lastRCUpdated; and leastRCRemainingLifetime == other.leastRCRemainingLifetime
and lastRCUpdated == other.lastRCUpdated;
} }
util::StatusObject util::StatusObject
@ -73,9 +73,9 @@ namespace llarp
{"numDistinctRCsReceived", numDistinctRCsReceived}, {"numDistinctRCsReceived", numDistinctRCsReceived},
{"numLateRCs", numLateRCs}, {"numLateRCs", numLateRCs},
// {"peakBandwidthBytesPerSec", peakBandwidthBytesPerSec}, // {"peakBandwidthBytesPerSec", peakBandwidthBytesPerSec},
{"longestRCReceiveIntervalMs", longestRCReceiveIntervalMs}, {"longestRCReceiveInterval", longestRCReceiveInterval.count()},
{"mostExpiredRCMs", mostExpiredRCMs}, {"leastRCRemainingLifetime", leastRCRemainingLifetime.count()},
{"lastRCUpdated", lastRCUpdated}, {"lastRCUpdated", lastRCUpdated.count()},
}; };
} }

@ -31,9 +31,9 @@ namespace llarp
int32_t numLateRCs = 0; int32_t numLateRCs = 0;
double peakBandwidthBytesPerSec = 0; double peakBandwidthBytesPerSec = 0;
int64_t longestRCReceiveIntervalMs = 0; llarp_time_t longestRCReceiveInterval = 0ms;
int64_t mostExpiredRCMs = 0; llarp_time_t leastRCRemainingLifetime = 0ms;
int64_t lastRCUpdated = 0; llarp_time_t lastRCUpdated = 0ms;
// not serialized // not serialized
bool stale = true; bool stale = true;

@ -131,27 +131,27 @@ TEST_CASE("Test PeerDb handleGossipedRC", "[PeerDb]")
auto stats = db.getCurrentPeerStats(id); auto stats = db.getCurrentPeerStats(id);
CHECK(stats.has_value()); CHECK(stats.has_value());
CHECK(stats.value().mostExpiredRCMs == 0); // not calculated on first received RC CHECK(stats.value().leastRCRemainingLifetime == 0ms); // not calculated on first received RC
CHECK(stats.value().numDistinctRCsReceived == 1); CHECK(stats.value().numDistinctRCsReceived == 1);
CHECK(stats.value().lastRCUpdated == 10000); CHECK(stats.value().lastRCUpdated == 10000ms);
now = 9s; now = 9s;
db.handleGossipedRC(rc, now); db.handleGossipedRC(rc, now);
stats = db.getCurrentPeerStats(id); stats = db.getCurrentPeerStats(id);
CHECK(stats.has_value()); CHECK(stats.has_value());
// these values should remain unchanged, this is not a new RC // these values should remain unchanged, this is not a new RC
CHECK(stats.value().mostExpiredRCMs == 0); CHECK(stats.value().leastRCRemainingLifetime == 0ms);
CHECK(stats.value().numDistinctRCsReceived == 1); CHECK(stats.value().numDistinctRCsReceived == 1);
CHECK(stats.value().lastRCUpdated == 10000); CHECK(stats.value().lastRCUpdated == 10000ms);
rc.last_updated = 11s; rc.last_updated = 11s;
db.handleGossipedRC(rc, now); db.handleGossipedRC(rc, now);
stats = db.getCurrentPeerStats(id); stats = db.getCurrentPeerStats(id);
// should be (previous expiration time - new received time) // should be (previous expiration time - new received time)
CHECK(stats.value().mostExpiredRCMs == ((10s + rcLifetime) - now).count()); CHECK(stats.value().leastRCRemainingLifetime == ((10s + rcLifetime) - now));
CHECK(stats.value().numDistinctRCsReceived == 2); CHECK(stats.value().numDistinctRCsReceived == 2);
CHECK(stats.value().lastRCUpdated == 11000); CHECK(stats.value().lastRCUpdated == 11000ms);
} }
TEST_CASE("Test PeerDb handleGossipedRC expiry calcs", "[PeerDb]") TEST_CASE("Test PeerDb handleGossipedRC expiry calcs", "[PeerDb]")
@ -194,24 +194,25 @@ TEST_CASE("Test PeerDb handleGossipedRC expiry calcs", "[PeerDb]")
db.handleGossipedRC(rc1, r1); db.handleGossipedRC(rc1, r1);
auto stats1 = db.getCurrentPeerStats(id); auto stats1 = db.getCurrentPeerStats(id);
CHECK(stats1.has_value()); CHECK(stats1.has_value());
CHECK(stats1.value().mostExpiredRCMs == 0); CHECK(stats1.value().leastRCRemainingLifetime == 0ms);
CHECK(stats1.value().numDistinctRCsReceived == 1); CHECK(stats1.value().numDistinctRCsReceived == 1);
CHECK(stats1.value().lastRCUpdated == s1.count()); CHECK(stats1.value().lastRCUpdated == s1);
db.handleGossipedRC(rc2, r2); db.handleGossipedRC(rc2, r2);
auto stats2 = db.getCurrentPeerStats(id); auto stats2 = db.getCurrentPeerStats(id);
CHECK(stats2.has_value()); CHECK(stats2.has_value());
CHECK(stats2.value().mostExpiredRCMs == (e1 - r2).count()); CHECK(stats2.value().leastRCRemainingLifetime == (e1 - r2));
CHECK(stats2.value().mostExpiredRCMs > 0); // ensure positive indicates healthy CHECK(stats2.value().leastRCRemainingLifetime > 0ms); // ensure positive indicates healthy
CHECK(stats2.value().numDistinctRCsReceived == 2); CHECK(stats2.value().numDistinctRCsReceived == 2);
CHECK(stats2.value().lastRCUpdated == s2.count()); CHECK(stats2.value().lastRCUpdated == s2);
db.handleGossipedRC(rc3, r3); db.handleGossipedRC(rc3, r3);
auto stats3 = db.getCurrentPeerStats(id); auto stats3 = db.getCurrentPeerStats(id);
CHECK(stats3.has_value()); CHECK(stats3.has_value());
CHECK(stats3.value().mostExpiredRCMs == (e2 - r3).count()); CHECK(stats3.value().leastRCRemainingLifetime == (e2 - r3));
CHECK( CHECK(
stats3.value().mostExpiredRCMs < 0); // ensure negative indicates unhealthy and we use min() stats3.value().leastRCRemainingLifetime
< 0ms); // ensure negative indicates unhealthy and we use min()
CHECK(stats3.value().numDistinctRCsReceived == 3); CHECK(stats3.value().numDistinctRCsReceived == 3);
CHECK(stats3.value().lastRCUpdated == s3.count()); CHECK(stats3.value().lastRCUpdated == s3);
} }

Loading…
Cancel
Save