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("numLateRCs", &PeerStats::numLateRCs),
make_column("peakBandwidthBytesPerSec", &PeerStats::peakBandwidthBytesPerSec),
make_column("longestRCReceiveIntervalMs", &PeerStats::longestRCReceiveIntervalMs),
make_column("mostExpiredRCMs", &PeerStats::mostExpiredRCMs)));
make_column("longestRCReceiveInterval", &PeerStats::longestRCReceiveInterval),
make_column("leastRCRemainingLifetime", &PeerStats::leastRCRemainingLifetime)));
}
using PeerDbStorage = decltype(initStorage(""));
} // 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];
stats.routerId = id.ToString();
const bool isNewRC = (stats.lastRCUpdated < rc.last_updated.count());
const bool isNewRC = (stats.lastRCUpdated < rc.last_updated);
if (isNewRC)
{
@ -211,20 +211,20 @@ namespace llarp
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),
// and this value will be negative for an unhealthy router
// 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)
stats.mostExpiredRCMs = expiry;
stats.leastRCRemainingLifetime = expiry;
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;
}
}

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

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

@ -131,27 +131,27 @@ TEST_CASE("Test PeerDb handleGossipedRC", "[PeerDb]")
auto stats = db.getCurrentPeerStats(id);
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().lastRCUpdated == 10000);
CHECK(stats.value().lastRCUpdated == 10000ms);
now = 9s;
db.handleGossipedRC(rc, now);
stats = db.getCurrentPeerStats(id);
CHECK(stats.has_value());
// 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().lastRCUpdated == 10000);
CHECK(stats.value().lastRCUpdated == 10000ms);
rc.last_updated = 11s;
db.handleGossipedRC(rc, now);
stats = db.getCurrentPeerStats(id);
// 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().lastRCUpdated == 11000);
CHECK(stats.value().lastRCUpdated == 11000ms);
}
TEST_CASE("Test PeerDb handleGossipedRC expiry calcs", "[PeerDb]")
@ -194,24 +194,25 @@ TEST_CASE("Test PeerDb handleGossipedRC expiry calcs", "[PeerDb]")
db.handleGossipedRC(rc1, r1);
auto stats1 = db.getCurrentPeerStats(id);
CHECK(stats1.has_value());
CHECK(stats1.value().mostExpiredRCMs == 0);
CHECK(stats1.value().leastRCRemainingLifetime == 0ms);
CHECK(stats1.value().numDistinctRCsReceived == 1);
CHECK(stats1.value().lastRCUpdated == s1.count());
CHECK(stats1.value().lastRCUpdated == s1);
db.handleGossipedRC(rc2, r2);
auto stats2 = db.getCurrentPeerStats(id);
CHECK(stats2.has_value());
CHECK(stats2.value().mostExpiredRCMs == (e1 - r2).count());
CHECK(stats2.value().mostExpiredRCMs > 0); // ensure positive indicates healthy
CHECK(stats2.value().leastRCRemainingLifetime == (e1 - r2));
CHECK(stats2.value().leastRCRemainingLifetime > 0ms); // ensure positive indicates healthy
CHECK(stats2.value().numDistinctRCsReceived == 2);
CHECK(stats2.value().lastRCUpdated == s2.count());
CHECK(stats2.value().lastRCUpdated == s2);
db.handleGossipedRC(rc3, r3);
auto stats3 = db.getCurrentPeerStats(id);
CHECK(stats3.has_value());
CHECK(stats3.value().mostExpiredRCMs == (e2 - r3).count());
CHECK(stats3.value().leastRCRemainingLifetime == (e2 - r3));
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().lastRCUpdated == s3.count());
CHECK(stats3.value().lastRCUpdated == s3);
}

Loading…
Cancel
Save