150 lines
4.3 KiB
C++
150 lines
4.3 KiB
C++
|
|
#ifndef DRIVER_UTIL_HPP
|
|
#define DRIVER_UTIL_HPP
|
|
|
|
#include "wrap-string.hpp"
|
|
#include "wrap-vector.hpp"
|
|
#include <string_view>
|
|
#include <fstream>
|
|
#include <ostream>
|
|
#include "drivenengine.hpp"
|
|
|
|
namespace drv {
|
|
|
|
void split_target(std::string_view target, std::string &cert, std::string &host, std::string &port);
|
|
|
|
|
|
std::vector<std::string> parse_control_lst(std::string_view ctrl);
|
|
|
|
|
|
class ReplayRecorder {
|
|
private:
|
|
std::ofstream f_;
|
|
UniqueDrivenEngine e_;
|
|
bool logging_;
|
|
|
|
void flush();
|
|
public:
|
|
// Initialization consists of three steps:
|
|
//
|
|
// 1. The constructor, which creates an empty ReplayRecorder.
|
|
// 2. Open the logfile for writing, if desired, using open_logfile.
|
|
// 3. Make the engine, using create_engine.
|
|
//
|
|
// After that, you can use drv_xxx methods to send messages to the
|
|
// engine. These messages will get logged if the replay log is open.
|
|
//
|
|
ReplayRecorder() : logging_(false) {}
|
|
|
|
// Open the logfile.
|
|
//
|
|
// If you're going to open a logfile, you must do so before
|
|
// creating the engine. Returns false if the logfile couldn't be
|
|
// opened.
|
|
//
|
|
bool open_logfile(const char *fn);
|
|
|
|
// Create the DrivenEngine.
|
|
//
|
|
// Returns false if the DrivenEngine couldn't be created.
|
|
//
|
|
bool create_engine(const char *kind);
|
|
|
|
// Report to the logger that the engine is about to exit cleanly,
|
|
// without any error.
|
|
//
|
|
void clean_exit();
|
|
|
|
// These don't need to be logged.
|
|
//
|
|
const eng::vector<int> &drv_get_listen_ports() const { return e_->drv_get_listen_ports(); }
|
|
const eng::vector<int> &drv_get_new_outgoing() const { return e_->drv_get_new_outgoing(); }
|
|
std::string_view drv_get_target(int chid) const { return e_->drv_get_target(chid); }
|
|
bool drv_outgoing_empty(int chid) const { return e_->drv_outgoing_empty(chid); }
|
|
bool drv_get_channel_released(int chid) const { return e_->drv_get_channel_released(chid); }
|
|
std::string_view drv_peek_outgoing(int chid) const { return e_->drv_peek_outgoing(chid); }
|
|
bool drv_get_rescan_lua_source() const { return e_->drv_get_rescan_lua_source(); }
|
|
bool drv_get_stop_driver() const { return e_->drv_get_stop_driver(); }
|
|
|
|
// These operations do need to be logged.
|
|
//
|
|
void drv_clear_new_outgoing();
|
|
void drv_sent_outgoing(int chid, int nbytes);
|
|
void drv_recv_incoming(int chid, std::string_view data);
|
|
void drv_notify_close(int chid, std::string_view err);
|
|
int drv_notify_accept(int port);
|
|
void drv_clear_lua_source();
|
|
void drv_add_lua_source(std::string_view fn, std::string_view data);
|
|
void drv_invoke_event_init(int argc, char *argv[]);
|
|
void drv_invoke_event_update(double clock);
|
|
};
|
|
|
|
class ReplayPlayer {
|
|
public:
|
|
enum Status {
|
|
ST_REPLAYING,
|
|
ST_CLEAN_EXIT,
|
|
ST_ERR_OPENING_LOGFILE,
|
|
ST_LOGFILE_ENDS_ABRUPTLY,
|
|
ST_LOGFILE_CORRUPT,
|
|
ST_NONDERMINISTIC,
|
|
ST_COULDNT_CREATE_ENGINE,
|
|
};
|
|
private:
|
|
std::ifstream f_;
|
|
UniqueDrivenEngine e_;
|
|
std::unique_ptr<char[]> buf_;
|
|
Status status_;
|
|
std::string logfn_;
|
|
std::string engine_;
|
|
bool enable_stdout_;
|
|
|
|
void set_status(Status e);
|
|
|
|
void create_engine();
|
|
void clean_exit();
|
|
void drv_clear_new_outgoing();
|
|
void drv_sent_outgoing();
|
|
void drv_recv_incoming();
|
|
void drv_notify_close();
|
|
void drv_notify_accept();
|
|
void drv_clear_lua_source();
|
|
void drv_add_lua_source();
|
|
void drv_invoke_event_init();
|
|
void drv_invoke_event_update();
|
|
public:
|
|
ReplayPlayer();
|
|
|
|
// Open the logfile for reading.
|
|
//
|
|
// Returns false if the logfile can't be opened.
|
|
//
|
|
bool open_logfile(const char *fn);
|
|
|
|
// Enable stdout.
|
|
//
|
|
// Normally, stdout is suppressed during replay.
|
|
// If you enable stdout, then the engine will print
|
|
// all the same messages it did when running in the
|
|
// first place.
|
|
//
|
|
void enable_stdout() { enable_stdout_ = true; }
|
|
|
|
// Execute a single step from the replay log.
|
|
//
|
|
// Returns a status code, which is usually ST_REPLAYING.
|
|
// If it's anything else, display the status and stop.
|
|
//
|
|
Status step();
|
|
|
|
// Print a status message.
|
|
//
|
|
// Print a message associated with the most recent status report.
|
|
//
|
|
void print_status(std::ostream &s);
|
|
};
|
|
|
|
} // namespace drv
|
|
|
|
#endif // DRIVER_UTIL_HPP
|