X-Git-Url: http://sraa.de/git/?a=blobdiff_plain;f=dol%2Fsrc%2Fdol%2Fvisitor%2Fhdsd%2Fscd%2Fscd_cont_slave_wrapper.cpp;fp=dol%2Fsrc%2Fdol%2Fvisitor%2Fhdsd%2Fscd%2Fscd_cont_slave_wrapper.cpp;h=0bc710a5b1fafd045b13d23d3da6c32f0bd0edb3;hb=8c411cf24ed0eb889191aaeafd8fa1e69081df42;hp=0000000000000000000000000000000000000000;hpb=dea7a4fb1ed110d3ce6e6d9255103d724bd66c0e;p=jump.git diff --git a/dol/src/dol/visitor/hdsd/scd/scd_cont_slave_wrapper.cpp b/dol/src/dol/visitor/hdsd/scd/scd_cont_slave_wrapper.cpp new file mode 100644 index 0000000..0bc710a --- /dev/null +++ b/dol/src/dol/visitor/hdsd/scd/scd_cont_slave_wrapper.cpp @@ -0,0 +1,182 @@ +#include "scd_cont_slave_wrapper.h" + +#include "scd_logging.h" +#include "scd_exception.h" + + +scd_cont_slave_wrapper::scd_cont_slave_wrapper(scd_simulator& sim, + const std::string& name): + _sim(sim), scd_cont_fsm(name), _name(name), _is_connected(false), + _st_init(sim, *this), _st_busy(sim, *this), _st_idle(sim, *this), + _st_done(sim, *this), _st_time_req(sim, *this), _st_time_ack(sim, *this), + _st_term_req(sim, *this), _st_term_ack(sim, *this), + _st_terminate(sim, *this), _st_terminated(sim, *this), _st_fail(sim, *this), + _st_failed(sim, *this) +{ + // set initial state + set_state(_st_init); +} + + +scd_cont_slave_wrapper::~scd_cont_slave_wrapper() +{ + if (_socket != NULL) + delete _socket; +} + + +const std::string& scd_cont_slave_wrapper::get_name() const { return _name; } + + +void scd_cont_slave_wrapper::connect(scd_socket* sock) +{ + if (!_is_connected) + { + _socket = sock; + _writer.set_socket(*_socket); + _reader.set_socket(*_socket); + _is_connected = true; + scd_info("slave \"" + _name + "\" connected"); + static_cast(_state)->set_connected(); + } + else + { + scd_warn("slave " + _name + " has already been connected"); + delete sock; + } +} // connect() + + +void scd_cont_slave_wrapper::send_command(scd_command* cmd) +{ + // register write event if not registered + if (!_writer.is_writing() && _is_connected && _socket->is_valid()) + _sim.get_poller().set_ev(*this, SOCK_EV_WRITE | SOCK_EV_READ + | SOCK_EV_CLOSE); + + // queue command to be written + _writer.queue_command(cmd); +} + + +bool scd_cont_slave_wrapper::is_sending() const +{ + return _writer.is_writing() && _is_connected && _socket->is_valid(); +} + + +void scd_cont_slave_wrapper::close() +{ + if (_is_connected) + _socket->close(); +} + + +void scd_cont_slave_wrapper::handle_sock_ev(sock_ev events) +{ + scd_stsw_base& state = *static_cast(_state); + + if (events & SOCK_EV_CLOSE) + { + _socket->close(); + scd_error("connection to slave \"" + _name + "\" lost"); + state.set_failed(); + return; + } + + if (events & SOCK_EV_READ) + { + _reader.read(); + + if (!_socket->is_valid()) + { + // connection closed + scd_error("connection to slave \"" + _name + "\" lost"); + state.set_failed(); + return; + } + + if (!_reader.is_reading() && !_reader.has_command()) + { + // received an illegal command + scd_error("received illegal command"); + state.set_fail(); + return; + } + + if (_reader.has_command()) + { + scd_command* cmd = _reader.get_command(); + _process_cmd(*cmd); + delete cmd; + } + + } // end read event + + if (events & SOCK_EV_WRITE) + { + _writer.write(); + + if (!_writer.is_writing()) + { + // done sending commands + _sim.get_poller().set_ev(*this, SOCK_EV_READ | SOCK_EV_CLOSE); + } + + if (!_socket->is_valid()) + { + scd_error("connection to slave \"" + _name + "\" lost"); + state.set_failed(); + return; + } + } // end write event + + +} // handle_sock_ev() + + +const scd_socket& scd_cont_slave_wrapper::get_sock() { return *_socket; } + + +void scd_cont_slave_wrapper::_process_cmd(const scd_command& cmd) +{ + if (cmd.get_type() != SCD_CM_CONTROL) + { + scd_warn("received non-control command"); + return; + } + + scd_stsw_base* state = static_cast(_state); + + switch(cmd.get_subtype()) + { + case SCD_CM_BUSY: + state->set_busy(); + break; + case SCD_CM_IDLE: + state->set_idle(cmd.get_time()); + break; + case SCD_CM_DONE: + state->set_done(); + break; + case SCD_CM_TIME_NACK: + state->recv_time_nack(); + break; + case SCD_CM_TIME_ACK: + state->recv_time_ack(); + break; + case SCD_CM_TERM_NACK: + state->recv_term_nack(); + break; + case SCD_CM_TERM_ACK: + state->recv_term_ack(); + break; + case SCD_CM_FAILED: + scd_error("slave \"" + _name + "\" failed"); + state->set_failed(); + break; + default: + scd_warn("received unknown command"); + break; + } +} // _process_cmd()