dol: initial dol commit
[jump.git] / dol / src / dol / visitor / hdsd / scd / scd_cont_man_slave.cpp
diff --git a/dol/src/dol/visitor/hdsd/scd/scd_cont_man_slave.cpp b/dol/src/dol/visitor/hdsd/scd/scd_cont_man_slave.cpp
new file mode 100644 (file)
index 0000000..7368ef9
--- /dev/null
@@ -0,0 +1,181 @@
+#include "scd_cont_man_slave.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+
+
+scd_cont_man_slave::scd_cont_man_slave(scd_simulator& sim):
+    scd_cont_fsm("slave"), _sim(sim),
+    _connector(sim, SCD_CM_NETSIM, sim.get_name()), _has_master(false),
+    _st_init(sim, *this), _st_busy(sim, *this), _st_fail(sim, *this),
+    _st_failed(sim, *this), _st_idle(sim, *this), _st_done(sim, *this),
+    _st_time_ack(sim, *this), _st_time(sim, *this), _st_term_ack(sim, *this),
+    _st_terminated(sim, *this)
+{
+    // set initial state
+    set_state(_st_init);
+}
+
+
+scd_cont_man_slave::~scd_cont_man_slave()
+{
+    if (_socket != NULL)
+        delete _socket;
+}
+
+
+void scd_cont_man_slave::set_socket()
+{
+    _socket = _connector.get_connection();
+    _writer.set_socket(*_socket);
+    _reader.set_socket(*_socket);
+} // set_socket()
+
+
+void scd_cont_man_slave::send_command(scd_command* cmd)
+{
+    // register write event if not registered
+    if (!_writer.is_writing() && _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_man_slave::is_sending()
+{
+    return _writer.is_writing() && _socket->is_valid();
+}
+
+
+void scd_cont_man_slave::close()
+{
+    if (_socket != NULL)
+        _socket->close();
+}
+
+
+void scd_cont_man_slave::set_master(const std::string& host, uint16_t port)
+{
+    if (!_has_master)
+        _connector.connect_to(host, port);
+    else
+    {
+        scd_error("master already set");
+        throw scd_exception("master already set");
+    }
+} // set_master()
+
+
+void scd_cont_man_slave::register_slave(const std::string& name)
+{
+    scd_error("simulator is slave, can not have other slaves");
+    throw scd_exception("simulator is slave");
+
+} // register_slave
+
+
+void scd_cont_man_slave::handle_sock_ev(sock_ev events)
+{
+    scd_sts_base& state = *static_cast<scd_sts_base*>(_state);
+
+    if (events & SOCK_EV_CLOSE)
+    {
+        scd_error("connection to master lost");
+        _socket->close();
+        state.set_failed();
+        return;
+    }
+
+    if (events & SOCK_EV_READ)
+    {
+        _reader.read();
+     
+        if (!_socket->is_valid())
+        {
+            // connection closed
+            scd_error("connection to master 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);
+        }
+    } // end write event
+
+    if (!_socket->is_valid())
+    {
+        scd_error("connection to master lost");
+        state.set_failed();
+    }
+    
+} // handle_sock_ev()
+
+
+const scd_socket& scd_cont_man_slave::get_sock() { return *_socket; }
+
+
+void scd_cont_man_slave::_process_cmd(scd_command& cmd)
+{
+    if (cmd.get_type() != SCD_CM_CONTROL)
+    {
+        scd_warn("received non-control command");
+        return;
+    }
+
+    scd_sts_base* state = static_cast<scd_sts_base*>(_state);
+
+    switch (cmd.get_subtype())
+    {
+    case SCD_CM_FAILED:
+        scd_error("master failed");
+        state->set_failed();
+        break;
+    case SCD_CM_TIME_REQ:
+        state->recv_time_req();
+        break;
+    case SCD_CM_TIME_NACK:
+        state->recv_time_nack();
+        break;
+    case SCD_CM_TIME:
+        state->recv_time(cmd.get_time());
+        break;
+    case SCD_CM_TERM_REQ:
+        state->recv_term_req();
+        break;
+    case SCD_CM_TERM_NACK:
+        state->recv_term_nack();
+        break;
+    case SCD_CM_TERM:
+        state->recv_term();
+        break;
+    default:
+        scd_warn("received unknown command");
+        break;
+    }
+} // _process_cmd()