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