Convert DrivenEngine rlog/wlog to use BaseWriter
This commit is contained in:
@@ -213,100 +213,42 @@ inline static const char *action_string(DrvAction act) {
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class PlayLogfile : public std::ofstream { using std::ofstream::ofstream; };
|
||||
class ReplayLogfile : public std::ifstream { using std::ifstream::ifstream; };
|
||||
|
||||
static uint8_t rlog_uint8(EngineWrapper *w) {
|
||||
uint8_t result;
|
||||
w->rlog->read((char *)&result, 1);
|
||||
if (!w->rlog->good()) return 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t rlog_uint32(EngineWrapper *w) {
|
||||
uint32_t result;
|
||||
w->rlog->read((char *)&result, 4);
|
||||
if (!w->rlog->good()) return 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint64_t rlog_uint64(EngineWrapper *w) {
|
||||
uint64_t result;
|
||||
w->rlog->read((char *)&result, 8);
|
||||
if (!w->rlog->good()) return 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
static double rlog_double(EngineWrapper *w) {
|
||||
double result;
|
||||
w->rlog->read((char *)&result, 8);
|
||||
if (!w->rlog->good()) return 0.0;
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string_view rlog_short_string(EngineWrapper *w) {
|
||||
uint32_t len = rlog_uint8(w);
|
||||
if (len == 255) {
|
||||
len = rlog_uint32(w);
|
||||
class PlayLogfile : public BaseWriter<PlayLogfile>, public std::ofstream {
|
||||
using std::ofstream::ofstream;
|
||||
public:
|
||||
void write_bytes(const char *n, size_t size) { write(n, size); }
|
||||
void raise_truncated() {
|
||||
fprintf(stderr, "number exceeds allowable size\n");
|
||||
std::abort();
|
||||
}
|
||||
assert (len <= DRV_SHORTSTRING_SIZE);
|
||||
if (len > 0) w->rlog->read(w->databuffer, len);
|
||||
if (!w->rlog->good()) return std::string_view();
|
||||
return std::string_view(w->databuffer, len);
|
||||
}
|
||||
|
||||
std::string rlog_string(EngineWrapper *w) {
|
||||
uint32_t len = rlog_uint8(w);
|
||||
if (len == 255) {
|
||||
len = rlog_uint32(w);
|
||||
void write_short_string(std::string_view v) {
|
||||
assert(v.size() < DRV_SHORTSTRING_SIZE);
|
||||
write_string(v);
|
||||
}
|
||||
std::string result(len, ' ');
|
||||
if (len > 0) w->rlog->read(&result[0], len);
|
||||
if (!w->rlog->good()) return "";
|
||||
return result;
|
||||
}
|
||||
|
||||
static void wlog_uint8(EngineWrapper *w, uint8_t v) {
|
||||
w->wlog->put((char)v);
|
||||
}
|
||||
|
||||
static void wlog_uint32(EngineWrapper *w, uint32_t v) {
|
||||
w->wlog->write((const char *)&v, 4);
|
||||
}
|
||||
|
||||
static void wlog_uint64(EngineWrapper *w, uint64_t v) {
|
||||
w->wlog->write((const char *)&v, 8);
|
||||
}
|
||||
|
||||
static void wlog_double(EngineWrapper *w, double v) {
|
||||
w->wlog->write((const char *)&v, 8);
|
||||
}
|
||||
|
||||
static void wlog_short_string(EngineWrapper *w, std::string_view v) {
|
||||
assert (v.size() <= DRV_SHORTSTRING_SIZE);
|
||||
if (v.size() >= 255) {
|
||||
wlog_uint8(w, 0xFF);
|
||||
wlog_uint32(w, v.size());
|
||||
} else {
|
||||
wlog_uint8(w, v.size());
|
||||
void write_cmd_hash(DrvAction act, uint32_t hash) {
|
||||
write_uint8(act);
|
||||
write_uint32(hash);
|
||||
}
|
||||
w->wlog->write(v.data(), v.size());
|
||||
}
|
||||
};
|
||||
|
||||
static void wlog_string(EngineWrapper *w, std::string_view v) {
|
||||
if (v.size() >= 255) {
|
||||
wlog_uint8(w, 0xFF);
|
||||
wlog_uint32(w, v.size());
|
||||
} else {
|
||||
wlog_uint8(w, v.size());
|
||||
class ReplayLogfile : public BaseReader<ReplayLogfile>, public std::ifstream {
|
||||
using std::ifstream::ifstream;
|
||||
public:
|
||||
using read_string_type = std::string;
|
||||
void read_bytes_into(char *n, size_t size) { read(n, size); }
|
||||
bool read_beyond_eof() { return !good(); }
|
||||
void raise_string_too_long() {
|
||||
fprintf(stderr, "string in logfile is too long");
|
||||
std::abort();
|
||||
}
|
||||
w->wlog->write(v.data(), v.size());
|
||||
}
|
||||
|
||||
static void wlog_cmd_hash(EngineWrapper *w, DrvAction act, uint32_t hash) {
|
||||
wlog_uint8(w, act);
|
||||
wlog_uint32(w, hash);
|
||||
}
|
||||
std::string_view read_short_string(EngineWrapper *w) {
|
||||
size_t size = read_length();
|
||||
assert(size <= DRV_SHORTSTRING_SIZE);
|
||||
if (size > 0) read(w->databuffer, size);
|
||||
if (!good()) return std::string_view();
|
||||
return std::string_view(w->databuffer, size);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -350,7 +292,7 @@ static void reset_wrapper(EngineWrapper *w, const char *format, ...) {
|
||||
|
||||
static void release(EngineWrapper *w) {
|
||||
if (w->wlog != nullptr) {
|
||||
wlog_cmd_hash(w, PLAY_RELEASE, eng::memhash());
|
||||
w->wlog->write_cmd_hash(PLAY_RELEASE, eng::memhash());
|
||||
}
|
||||
reset_wrapper(w, "");
|
||||
};
|
||||
@@ -630,12 +572,12 @@ static void play_initialize(EngineWrapper *w, uint32_t argc, char **argv, uint32
|
||||
|
||||
// If we have a logfile, then log this initialization.
|
||||
if (w->wlog != nullptr) {
|
||||
wlog_cmd_hash(w, PLAY_INITIALIZE, eng::memhash());
|
||||
wlog_uint32(w, argc);
|
||||
w->wlog->write_cmd_hash(PLAY_INITIALIZE, eng::memhash());
|
||||
w->wlog->write_uint32(argc);
|
||||
for (uint32_t i = 0; i < argc; i++) {
|
||||
wlog_string(w, argv[i]);
|
||||
w->wlog->write_string(argv[i]);
|
||||
}
|
||||
wlog_string(w, std::string_view(srcpk, srcpklen));
|
||||
w->wlog->write_string(std::string_view(srcpk, srcpklen));
|
||||
w->wlog->flush();
|
||||
}
|
||||
|
||||
@@ -662,11 +604,11 @@ static void play_initialize(EngineWrapper *w, uint32_t argc, char **argv, uint32
|
||||
static void replay_initialize(EngineWrapper *w) {
|
||||
assert(w->rlog != nullptr);
|
||||
std::vector<std::string> argvstr;
|
||||
uint32_t argc = rlog_uint32(w);
|
||||
uint32_t argc = w->rlog->read_uint32();
|
||||
for (uint32_t i = 0; i < argc; i++) {
|
||||
argvstr.push_back(rlog_string(w));
|
||||
argvstr.push_back(w->rlog->read_string());
|
||||
}
|
||||
std::string srcpk = rlog_string(w);
|
||||
std::string srcpk = w->rlog->read_string();
|
||||
|
||||
if (!w->rlog->good()) {
|
||||
return reset_wrapper(w, "replay log corrupt in replay_initialize");
|
||||
@@ -697,7 +639,7 @@ static void replay_initialize(EngineWrapper *w) {
|
||||
static void play_clear_new_outgoing(EngineWrapper *w) {
|
||||
assert(w->rlog == nullptr);
|
||||
if (w->wlog != nullptr) {
|
||||
wlog_cmd_hash(w, PLAY_CLEAR_NEW_OUTGOING, eng::memhash());
|
||||
w->wlog->write_cmd_hash(PLAY_CLEAR_NEW_OUTGOING, eng::memhash());
|
||||
w->wlog->flush();
|
||||
}
|
||||
w->engine->drv_clear_new_outgoing();
|
||||
@@ -717,19 +659,19 @@ static void play_sent_outgoing(EngineWrapper *w, uint32_t chid, uint32_t nbytes)
|
||||
uint32_t ndata; const char *data;
|
||||
w->engine->drv_get_outgoing(chid, &ndata, &data);
|
||||
assert(nbytes <= ndata);
|
||||
wlog_cmd_hash(w, PLAY_SENT_OUTGOING, eng::memhash());
|
||||
wlog_uint32(w, chid);
|
||||
wlog_uint32(w, nbytes);
|
||||
wlog_uint64(w, SpookyHash::QkHash64(data, nbytes));
|
||||
w->wlog->write_cmd_hash(PLAY_SENT_OUTGOING, eng::memhash());
|
||||
w->wlog->write_uint32(chid);
|
||||
w->wlog->write_uint32(nbytes);
|
||||
w->wlog->write_uint64(SpookyHash::QkHash64(data, nbytes));
|
||||
w->wlog->flush();
|
||||
}
|
||||
w->engine->drv_sent_outgoing(chid, nbytes);
|
||||
}
|
||||
|
||||
static void replay_sent_outgoing(EngineWrapper *w) {
|
||||
uint32_t chid = rlog_uint32(w);
|
||||
uint32_t nbytes = rlog_uint32(w);
|
||||
uint64_t hash = rlog_uint64(w);
|
||||
uint32_t chid = w->rlog->read_uint32();
|
||||
uint32_t nbytes = w->rlog->read_uint32();
|
||||
uint64_t hash = w->rlog->read_uint64();
|
||||
|
||||
if (!w->rlog->good()) {
|
||||
return reset_wrapper(w, "replay log corrupt in replay_sent_outgoing");
|
||||
@@ -753,18 +695,18 @@ static void replay_sent_outgoing(EngineWrapper *w) {
|
||||
static void play_recv_incoming(EngineWrapper *w, uint32_t chid, uint32_t len, const char *data) {
|
||||
assert(w->rlog == nullptr);
|
||||
if (w->wlog != nullptr) {
|
||||
wlog_cmd_hash(w, PLAY_RECV_INCOMING, eng::memhash());
|
||||
wlog_uint32(w, chid);
|
||||
wlog_short_string(w, std::string_view(data, len));
|
||||
w->wlog->write_cmd_hash(PLAY_RECV_INCOMING, eng::memhash());
|
||||
w->wlog->write_uint32(chid);
|
||||
w->wlog->write_short_string(std::string_view(data, len));
|
||||
w->wlog->flush();
|
||||
}
|
||||
w->engine->drv_recv_incoming(chid, len, data);
|
||||
}
|
||||
|
||||
static void replay_recv_incoming(EngineWrapper *w) {
|
||||
uint32_t chid = rlog_uint32(w);
|
||||
std::string_view data = rlog_short_string(w);
|
||||
|
||||
uint32_t chid = w->rlog->read_uint32();
|
||||
std::string_view data = w->rlog->read_short_string(w);
|
||||
|
||||
if (!w->rlog->good()) {
|
||||
return reset_wrapper(w, "replay log corrupt in replay_recv_incoming");
|
||||
}
|
||||
@@ -779,9 +721,9 @@ static void replay_recv_incoming(EngineWrapper *w) {
|
||||
static void play_notify_close(EngineWrapper *w, uint32_t chid, uint32_t len, const char *data) {
|
||||
assert(w->rlog == nullptr);
|
||||
if (w->wlog != nullptr) {
|
||||
wlog_cmd_hash(w, PLAY_NOTIFY_CLOSE, eng::memhash());
|
||||
wlog_uint32(w, chid);
|
||||
wlog_string(w, std::string_view(data, len));
|
||||
w->wlog->write_cmd_hash(PLAY_NOTIFY_CLOSE, eng::memhash());
|
||||
w->wlog->write_uint32(chid);
|
||||
w->wlog->write_string(std::string_view(data, len));
|
||||
w->wlog->flush();
|
||||
}
|
||||
|
||||
@@ -789,8 +731,8 @@ static void play_notify_close(EngineWrapper *w, uint32_t chid, uint32_t len, con
|
||||
}
|
||||
|
||||
static void replay_notify_close(EngineWrapper *w) {
|
||||
uint32_t chid = rlog_uint32(w);
|
||||
std::string message = rlog_string(w);
|
||||
uint32_t chid = w->rlog->read_uint32();
|
||||
std::string message = w->rlog->read_string();
|
||||
|
||||
if (!w->rlog->good()) {
|
||||
return reset_wrapper(w, "replay log corrupt in replay_notify_close");
|
||||
@@ -806,8 +748,8 @@ static void replay_notify_close(EngineWrapper *w) {
|
||||
static uint32_t play_notify_accept(EngineWrapper *w, uint32_t port) {
|
||||
assert(w->rlog == nullptr);
|
||||
if (w->wlog != nullptr) {
|
||||
wlog_cmd_hash(w, PLAY_NOTIFY_ACCEPT, eng::memhash());
|
||||
wlog_uint32(w, port);
|
||||
w->wlog->write_cmd_hash(PLAY_NOTIFY_ACCEPT, eng::memhash());
|
||||
w->wlog->write_uint32(port);
|
||||
w->wlog->flush();
|
||||
}
|
||||
|
||||
@@ -815,7 +757,7 @@ static uint32_t play_notify_accept(EngineWrapper *w, uint32_t port) {
|
||||
}
|
||||
|
||||
static void replay_notify_accept(EngineWrapper *w) {
|
||||
uint32_t port = rlog_uint32(w);
|
||||
uint32_t port = w->rlog->read_uint32();
|
||||
|
||||
if (!w->rlog->good()) {
|
||||
return reset_wrapper(w, "replay log corrupt in replay_notify_accept");
|
||||
@@ -831,8 +773,8 @@ static void replay_notify_accept(EngineWrapper *w) {
|
||||
static void play_invoke_event_update(EngineWrapper *w, double clock) {
|
||||
assert(w->rlog == nullptr);
|
||||
if (w->wlog != nullptr) {
|
||||
wlog_cmd_hash(w, PLAY_INVOKE_EVENT_UPDATE, eng::memhash());
|
||||
wlog_double(w, clock);
|
||||
w->wlog->write_cmd_hash(PLAY_INVOKE_EVENT_UPDATE, eng::memhash());
|
||||
w->wlog->write_double(clock);
|
||||
w->wlog->flush();
|
||||
}
|
||||
|
||||
@@ -840,8 +782,7 @@ static void play_invoke_event_update(EngineWrapper *w, double clock) {
|
||||
}
|
||||
|
||||
static void replay_invoke_event_update(EngineWrapper *w) {
|
||||
double clock = rlog_double(w);
|
||||
|
||||
double clock = w->rlog->read_double();
|
||||
if (!w->rlog->good()) {
|
||||
return reset_wrapper(w, "replay log corrupt in replay_event_update");
|
||||
}
|
||||
@@ -856,8 +797,8 @@ static void replay_invoke_event_update(EngineWrapper *w) {
|
||||
void play_set_lua_source(EngineWrapper *w, uint32_t srcpklen, const char *srcpk) {
|
||||
assert(w->rlog == nullptr);
|
||||
if (w->wlog != nullptr) {
|
||||
wlog_cmd_hash(w, PLAY_SET_LUA_SOURCE, eng::memhash());
|
||||
wlog_string(w, std::string_view(srcpk, srcpklen));
|
||||
w->wlog->write_cmd_hash(PLAY_SET_LUA_SOURCE, eng::memhash());
|
||||
w->wlog->write_string(std::string_view(srcpk, srcpklen));
|
||||
w->wlog->flush();
|
||||
}
|
||||
|
||||
@@ -865,7 +806,7 @@ void play_set_lua_source(EngineWrapper *w, uint32_t srcpklen, const char *srcpk)
|
||||
}
|
||||
|
||||
void replay_set_lua_source(EngineWrapper *w) {
|
||||
std::string srcpack = rlog_string(w);
|
||||
std::string srcpack = w->rlog->read_string();
|
||||
|
||||
if (!w->rlog->good()) {
|
||||
return reset_wrapper(w, "replay log corrupt in replay_set_lua_source");
|
||||
@@ -900,8 +841,8 @@ static void replaycore_initialize(EngineWrapper *w, const char *logfn) {
|
||||
}
|
||||
|
||||
// Read one step from the logfile, and make sure it's an initialize step.
|
||||
uint8_t code = rlog_uint8(w);
|
||||
int hash = rlog_uint32(w);
|
||||
uint8_t code = w->rlog->read_uint8();
|
||||
int hash = w->rlog->read_uint32();
|
||||
if (!w->rlog->good()) {
|
||||
return reset_wrapper(w, "logfile corrupt in initial step");
|
||||
}
|
||||
@@ -924,11 +865,11 @@ static void replaycore_step(EngineWrapper *w) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t code = rlog_uint8(w);
|
||||
uint8_t code = w->rlog->read_uint8();
|
||||
if (w->rlog->eof()) {
|
||||
return reset_wrapper(w, "logfile terminated abruptly");
|
||||
}
|
||||
int hash = rlog_uint32(w);
|
||||
int hash = w->rlog->read_uint32();
|
||||
if (!w->rlog->good()) {
|
||||
return reset_wrapper(w, "logfile corrupt in replay step");
|
||||
}
|
||||
|
||||
@@ -381,7 +381,11 @@ public:
|
||||
// Throw a StreamCorruption exception.
|
||||
void raise_truncated() { throw StreamCorruption(); }
|
||||
void raise_string_too_long() { throw StreamCorruption(); }
|
||||
|
||||
|
||||
// This is always false, because this module throws exceptions
|
||||
// when reading beyond EOF.
|
||||
bool read_beyond_eof() { return false; }
|
||||
|
||||
private:
|
||||
// Start and end of the allocated block.
|
||||
char *buf_lo_;
|
||||
|
||||
@@ -31,14 +31,13 @@
|
||||
// void write_length(size_t data)
|
||||
// void write_string(std::string_view data)
|
||||
//
|
||||
// In order to derive from BaseWriter, you must use the CRTP pattern:
|
||||
// You should derive from BaseWriter using the CRTP pattern:
|
||||
//
|
||||
// class DerivedWriter : public BaseWriter<DerivedWriter>
|
||||
//
|
||||
// And you must provide two methods in the derived class:
|
||||
// You must provide two methods in the derived class:
|
||||
//
|
||||
// write_bytes(const char *n, size_t size)
|
||||
//
|
||||
// raise_truncated()
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
@@ -111,15 +110,16 @@ public:
|
||||
// String read_string_limit(uint64_t size);
|
||||
// String read_string();
|
||||
//
|
||||
// In order to derive from BaseReader, you must use the CRTP pattern:
|
||||
// You should derive from BaseReader using the CRTP pattern:
|
||||
//
|
||||
// class DerivedReader : public BaseReader<DerivedReader>
|
||||
//
|
||||
// The derived class must provide:
|
||||
//
|
||||
// using read_string_type = std::string; // or similar
|
||||
// using read_string_type = std::string; // or compatible
|
||||
// void read_bytes_into(char *n, size_t size)
|
||||
// void raise_string_too_long();
|
||||
// bool read_beyond_eof();
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -129,7 +129,9 @@ protected:
|
||||
template<class T>
|
||||
T read_value_core() {
|
||||
T result;
|
||||
static_cast<Derived*>(this)->read_bytes_into((char *)(&result), sizeof(result));
|
||||
Derived *dthis = static_cast<Derived*>(this);
|
||||
dthis->read_bytes_into((char *)(&result), sizeof(result));
|
||||
if (dthis->read_beyond_eof()) result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -159,9 +161,11 @@ public:
|
||||
|
||||
auto read_string_limit(uint64_t limit) {
|
||||
size_t len = read_length();
|
||||
if (len > limit) static_cast<Derived*>(this)->raise_string_too_long();
|
||||
Derived *dthis = static_cast<Derived*>(this);
|
||||
if (len > limit) dthis->raise_string_too_long();
|
||||
typename Derived::read_string_type result(len, ' ');
|
||||
static_cast<Derived*>(this)->read_bytes_into(&(result[0]), len);
|
||||
dthis->read_bytes_into(&(result[0]), len);
|
||||
if (dthis->read_beyond_eof()) result.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user