Diff xmit of ID player pools

This commit is contained in:
2021-07-13 16:34:24 -04:00
parent 1904f03dad
commit 4357fd647f
4 changed files with 196 additions and 24 deletions

View File

@@ -1,5 +1,6 @@
#include "idalloc.hpp"
#include <iostream>
#include <map>
static int64_t nthbatch(int64_t n) {
@@ -121,7 +122,15 @@ void IdPlayerPool::disable_fifo() {
fifo_enabled_ = false;
}
void IdPlayerPool::purge() {
void IdPlayerPool::test_push_back(int64_t range) {
ranges_.push_back(range);
}
void IdPlayerPool::test_pop_front() {
ranges_.pop_front();
}
void IdPlayerPool::test_clear_ranges() {
ranges_.clear();
}
@@ -184,6 +193,96 @@ void IdPlayerPool::deserialize(StreamBuffer *sb) {
}
}
bool IdPlayerPool::exactly_equal(const IdPlayerPool &other) const {
if (fifo_enabled_ != other.fifo_enabled_) return false;
if (ranges_.size() != other.ranges_.size()) return false;
for (int i = 0; i < int(ranges_.size()); i++) {
if (ranges_[i] != other.ranges_[i]) {
return false;
}
}
return true;
}
bool IdPlayerPool::valid() const {
if ((!fifo_enabled_) && (ranges_.size() > 0)) return false;
if (ranges_.size() > 250) return false;
return true;
}
bool IdPlayerPool::make_patch(const IdPlayerPool &auth, StreamBuffer *sb) const {
assert(valid());
assert(auth.valid());
assert(global_->queue_fill() == auth.global_->queue_fill());
// The first byte.
// 0 no differences
// 1 fifo disabled and ranges empty
// 2+ fifo enabled and N-2 ranges.
//
if (exactly_equal(auth)) {
sb->write_uint8(0);
return false;
}
if (!auth.fifo_enabled_) {
sb->write_uint8(1);
return true;
}
sb->write_uint8(auth.ranges_.size() + 2);
// Build up an index of the known IDs.
std::map<int64_t, int> index;
for (int i = 0; i < int(ranges_.size()); i++) {
index[ranges_[i]] = i;
}
// Write the ranges, but encode known IDs in one byte.
for (int i = 0; i < int(auth.ranges_.size()); i++) {
int64_t n = auth.ranges_[i];
auto iter = index.find(n);
if (iter == index.end()) {
sb->write_uint8(255);
sb->write_int64(n);
} else {
int slot = iter->second;
sb->write_uint8(slot);
}
}
return true;
}
void IdPlayerPool::apply_patch(StreamBuffer *sb) {
// read the header byte
int nranges = sb->read_uint8();
if (nranges == 0) {
return;
}
if (nranges == 1) {
fifo_enabled_ = false;
ranges_.clear();
return;
}
fifo_enabled_ = true;
nranges -= 2;
std::deque<int64_t> old = std::move(ranges_);
ranges_.clear();
for (int i = 0; i < nranges; i++) {
int index = sb->read_uint8();
if (index < 255) {
assert(index < int(old.size()));
ranges_.push_back(old[index]);
} else {
ranges_.push_back(sb->read_int64());
}
}
}
LuaDefine(unittests_idalloc, "c") {
IdGlobalPool gp;
IdPlayerPool pp(&gp);
@@ -244,7 +343,7 @@ LuaDefine(unittests_idalloc, "c") {
LuaAssert(L, gp.get_batch() == nthbatch(2));
// In the synchronous model, refill should do nothing.
pp.purge();
pp.test_clear_ranges();
pp.enable_fifo();
gp.init_synch(3);
pp.refill();
@@ -255,7 +354,7 @@ LuaDefine(unittests_idalloc, "c") {
// In the master model, with fifo disabled. Fifo should remain
// empty, but batches should be returned.
pp.purge();
pp.test_clear_ranges();
pp.disable_fifo();
gp.init_master(3);
pp.refill();
@@ -265,7 +364,7 @@ LuaDefine(unittests_idalloc, "c") {
LuaAssert(L, pp.get_batch() == nthbatch(1));
// Test refill from master (with enabled fifo).
pp.purge();
pp.test_clear_ranges();
pp.enable_fifo();
gp.init_master(3);
pp.refill();
@@ -285,7 +384,7 @@ LuaDefine(unittests_idalloc, "c") {
LuaAssert(L, gp.get_batch() == nthbatch(6));
// Try preparing a thread and salvaging a thread.
pp.purge();
pp.test_clear_ranges();
pp.enable_fifo();
gp.init_master(3);
lua_setnextid(L, 0);
@@ -328,12 +427,12 @@ LuaDefine(unittests_idalloc, "c") {
gp.init_master(3);
gpds.init_synch(5);
LuaAssert(L, gp.get_batch() == nthbatch(0));
pp.purge();
pp.test_clear_ranges();
pp.enable_fifo();
pp.refill();
LuaAssert(L, pp.fifo_enabled());
LuaAssert(L, pp.size() == 3);
ppds.purge();
ppds.test_clear_ranges();
pp.serialize(&sb);
ppds.deserialize(&sb);
LuaAssert(L, ppds.fifo_enabled());
@@ -342,5 +441,41 @@ LuaDefine(unittests_idalloc, "c") {
LuaAssert(L, ppds.get_batch() == nthbatch(2));
LuaAssert(L, ppds.get_batch() == nthbatch(3));
// Difference transmit compare two empty pools.
gp.init_master(3);
gpds.init_master(3);
pp.test_clear_ranges();
ppds.test_clear_ranges();
pp.enable_fifo();
ppds.enable_fifo();
// Check case: no differences.
sb.clear();
LuaAssert(L, !ppds.make_patch(pp, &sb));
ppds.apply_patch(&sb);
LuaAssert(L, ppds.exactly_equal(pp));
// Add some values to master pool
pp.test_push_back(123);
pp.test_push_back(456);
// transmit and compare. Add extra bytes
sb.clear();
LuaAssert(L, ppds.make_patch(pp, &sb));
sb.write_uint32(0);
ppds.apply_patch(&sb);
LuaAssert(L, sb.write_count() - sb.read_count() == 4);
LuaAssert(L, ppds.exactly_equal(pp));
// Pop a value from master pool
pp.test_pop_front();
pp.test_push_back(789);
// transmit and compare.
sb.clear();
LuaAssert(L, ppds.make_patch(pp, &sb));
ppds.apply_patch(&sb);
LuaAssert(L, ppds.exactly_equal(pp));
return 0;
}