dol: initial dol commit
[jump.git] / dol / src / dol / visitor / hdsd / scd / scd_cont_man_slave.cpp
1 #include "scd_cont_man_slave.h"
2
3 #include "scd_logging.h"
4 #include "scd_exception.h"
5
6
7 scd_cont_man_slave::scd_cont_man_slave(scd_simulator& sim):
8     scd_cont_fsm("slave"), _sim(sim),
9     _connector(sim, SCD_CM_NETSIM, sim.get_name()), _has_master(false),
10     _st_init(sim, *this), _st_busy(sim, *this), _st_fail(sim, *this),
11     _st_failed(sim, *this), _st_idle(sim, *this), _st_done(sim, *this),
12     _st_time_ack(sim, *this), _st_time(sim, *this), _st_term_ack(sim, *this),
13     _st_terminated(sim, *this)
14 {
15     // set initial state
16     set_state(_st_init);
17 }
18
19
20 scd_cont_man_slave::~scd_cont_man_slave()
21 {
22     if (_socket != NULL)
23         delete _socket;
24 }
25
26
27 void scd_cont_man_slave::set_socket()
28 {
29     _socket = _connector.get_connection();
30     _writer.set_socket(*_socket);
31     _reader.set_socket(*_socket);
32 } // set_socket()
33
34
35 void scd_cont_man_slave::send_command(scd_command* cmd)
36 {
37     // register write event if not registered
38     if (!_writer.is_writing() && _socket->is_valid())
39         _sim.get_poller().set_ev(*this, SOCK_EV_WRITE | SOCK_EV_READ
40                 | SOCK_EV_CLOSE);
41
42     // queue command to be written
43     _writer.queue_command(cmd);
44 }
45
46
47 bool scd_cont_man_slave::is_sending()
48 {
49     return _writer.is_writing() && _socket->is_valid();
50 }
51
52
53 void scd_cont_man_slave::close()
54 {
55     if (_socket != NULL)
56         _socket->close();
57 }
58
59
60 void scd_cont_man_slave::set_master(const std::string& host, uint16_t port)
61 {
62     if (!_has_master)
63         _connector.connect_to(host, port);
64     else
65     {
66         scd_error("master already set");
67         throw scd_exception("master already set");
68     }
69 } // set_master()
70
71
72 void scd_cont_man_slave::register_slave(const std::string& name)
73 {
74     scd_error("simulator is slave, can not have other slaves");
75     throw scd_exception("simulator is slave");
76
77 } // register_slave
78
79
80 void scd_cont_man_slave::handle_sock_ev(sock_ev events)
81 {
82     scd_sts_base& state = *static_cast<scd_sts_base*>(_state);
83
84     if (events & SOCK_EV_CLOSE)
85     {
86         scd_error("connection to master lost");
87         _socket->close();
88         state.set_failed();
89         return;
90     }
91
92     if (events & SOCK_EV_READ)
93     {
94         _reader.read();
95      
96         if (!_socket->is_valid())
97         {
98             // connection closed
99             scd_error("connection to master lost");
100             state.set_failed();
101             return;
102         }
103
104         if (!_reader.is_reading() && !_reader.has_command())
105         {
106             // received an illegal command
107             scd_error("received illegal command");
108             state.set_fail();
109             return;
110         }
111
112         if (_reader.has_command())
113         {
114             scd_command* cmd = _reader.get_command();
115             _process_cmd(*cmd);
116             delete cmd;
117         }
118
119     } // end read event
120
121     if (events & SOCK_EV_WRITE)
122     {
123         _writer.write();
124         if (!_writer.is_writing())
125         {
126             // done sending commands
127             _sim.get_poller().set_ev(*this, SOCK_EV_READ | SOCK_EV_CLOSE);
128         }
129     } // end write event
130
131     if (!_socket->is_valid())
132     {
133         scd_error("connection to master lost");
134         state.set_failed();
135     }
136     
137 } // handle_sock_ev()
138
139
140 const scd_socket& scd_cont_man_slave::get_sock() { return *_socket; }
141
142
143 void scd_cont_man_slave::_process_cmd(scd_command& cmd)
144 {
145     if (cmd.get_type() != SCD_CM_CONTROL)
146     {
147         scd_warn("received non-control command");
148         return;
149     }
150
151     scd_sts_base* state = static_cast<scd_sts_base*>(_state);
152
153     switch (cmd.get_subtype())
154     {
155     case SCD_CM_FAILED:
156         scd_error("master failed");
157         state->set_failed();
158         break;
159     case SCD_CM_TIME_REQ:
160         state->recv_time_req();
161         break;
162     case SCD_CM_TIME_NACK:
163         state->recv_time_nack();
164         break;
165     case SCD_CM_TIME:
166         state->recv_time(cmd.get_time());
167         break;
168     case SCD_CM_TERM_REQ:
169         state->recv_term_req();
170         break;
171     case SCD_CM_TERM_NACK:
172         state->recv_term_nack();
173         break;
174     case SCD_CM_TERM:
175         state->recv_term();
176         break;
177     default:
178         scd_warn("received unknown command");
179         break;
180     }
181 } // _process_cmd()