Progress on mingw driver

This commit is contained in:
2021-10-07 14:58:20 -04:00
parent bce756d1fd
commit e7f55a2411
16 changed files with 405 additions and 172 deletions

View File

@@ -2,26 +2,16 @@
//
// DrivenEngine
//
// This module achieves two goals:
// This module embodies the idea of an "event-driven game engine." We want the
// engine to be event-driven because an event-driven engine is a deterministic
// state machine. That, in turn, makes it possible to do replay logging.
//
// * Makes it possible to do replay logging.
// * Makes the engine act like a deterministic state machine.
// The DrivenEngine module provides two APIs: the 'engine-side' API, and the
// 'driver-side' API.
//
// We want to implement replay logging. That means we want to be able to run
// the engine, keeping a log, then "replay" that execution later.
//
// Unfortunately, I/O makes this difficult. Suppose that during the execution
// of the server, the server reads a lua source file. Later, we want to replay
// that execution, but the lua source file has changed on disk. When the engine
// reads the lua source file, we need it to "read" the data that *used* to be
// there, not the data that's currently there.
//
// To make it work, all I/O has to operate in one of two modes: either it can be
// real I/O, or it can be simulated I/O that retrieves data from the logfile.
//
// This module, DrivenEngine, provides an API for the engine to do all its I/O.
// It provides a variety of methods to open sockets, read and write sockets,
// read lua source, get the clock, and so forth.
// The engine-side API looks like a typical collection of I/O primitives. It
// includes methods to open sockets, read and write sockets, read lua source,
// get the clock, and so forth.
//
// But in reality, these I/O functions don't ever call operating system
// functions like "read" or "write" or "connect." They don't call the operating
@@ -71,15 +61,11 @@
// - If the engine asked that the lua source be refreshed, read the source
// from disk and call 'drv_set_lua_source'.
//
// - List all existing channels using drv_list_channels.
// - Get a list of recently-closed channels using drv_get_closed_channels.
// Close any socket associated with these channels and free all resources.
//
// - If there are any new channels in the channel list, use
// drv_get_channel_target to fetch the target host, then create a socket
// and open the connection. Associate the socket with the channel.
//
// - If the channel list is missing a previously-known channel, then that
// channel was deleted by the engine. Clean up the channel's data and
// close the socket, if any.
// - Get a list of recently-opened channels using drv_get_opened_channels.
// Open new outgoing connections for these channels.
//
// - Do an OS 'poll'. The poll should include the sockets for all channels
// in the channel list, all listening ports, and stdio.
@@ -232,32 +218,23 @@ public:
//
//////////////////////////////////////////////////////////////
// Run in logging mode. In this mode, the 'drv' methods will write records
// into the logfile, making it possible to replay the exact sequence of drv
// methods that were invoked. The replay log will be flushed and closed
// automatically in the event of a crash, or if it exceeds the maximum size.
// The maximum channel ID plus one.
//
void drv_logmode_write(const std::string &filename, int64_t maxsize);
static const int MAX_CHAN = 256;
// Run in replay mode. In this mode, the only function the driver may call
// is 'drv_step_logfile.' Each time this method is called, a single drv_xxx
// method will be called, as requested by the logfile.
// Get a list of all recently-closed channels. The driver should
// discard all socket information associated with these channels.
// Caution: this may contain channels that the driver has never
// heard of. In that case, just ignore the close-request.
//
void drv_logmode_replay(const std::string &filename);
// Run in non-logging mode. In this mode, no logfile will be read or written
// in this mode.
//
void drv_logmode_none();
// Get a list of all non-closed existing channels. This may include new
// channels that were created using 'new_outgoing_channel'. It may also be
// missing channels that were deleted. It is up to the driver to update its
// internal data structures to 'match' this list. Channel number zero is
// always present, it is the stdio channel.
//
void drv_list_channels(std::vector<int> &channels);
void drv_get_new_closed(std::set<int> &opened);
// Get a list of all recently-opened channels that were created using
// drv_new_outgoing_channel. The driver should initiate outgoing
// connections for these channels.
//
void drv_get_new_outgoing(std::set<int> &closed);
// Get the target of a channel. A target is a string like
// "www.whatever.com:80". It indicates the host and port that the channel
// is supposed to be talking to. Non-socket channels and incoming channels
@@ -265,6 +242,10 @@ public:
//
const std::string &drv_get_target(int chid);
// Return true if the outgoing buffer is empty.
//
bool drv_outgoing_empty(int chid);
// Get a pointer to the bytes in the outgoing buffer. The pointer returned
// here is naturally only valid until the buffer is changed. This function
// is used for all channels, including sockets and stdio.
@@ -281,7 +262,7 @@ public:
// bytes to be appended to the incoming buffer. This function is used for
// all channels, including sockets and stdio.
//
void drv_recv_incoming(int chid, int nbytes, char *bytes);
void drv_recv_incoming(int chid, int nbytes, const char *bytes);
// Notify the channel that the connection was closed. This includes all
// sorts of closes, including friendly termination, all the way to network
@@ -325,11 +306,6 @@ public:
//
bool drv_get_stop_driver();
// In replay mode, perform a single step of the logfile. Returns true
// if the logfile was not empty.
//
bool drv_step_logfile();
//////////////////////////////////////////////////////////////
//
// Creation and Destruction.
@@ -360,15 +336,20 @@ public:
static DrivenEngine *get();
private:
// Get a channel by channel ID.
// Find a currently-unused channel ID. Channel IDs
// are small integers that are reused.
int find_unused_chid();
// Get the channel associated with the specified channel ID.
Channel *get_chid(int chid);
private:
Channel *channels_[MAX_CHAN];
int next_unused_chid_;
std::unique_ptr<Channel> stdio_channel_;
int next_channel_id_;
std::map<int, Channel *> channels_;
Channel *recent_channel_;
std::vector<std::unique_ptr<Channel>> accepted_channels_;
std::set<int> new_closed_;
std::set<int> new_outgoing_;
util::LuaSourcePtr lua_source_;
bool rescan_lua_source_;
double clock_;