VOM fixes and logger improvements
[vpp.git] / src / vpp-api / vom / hw.cpp
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include "vom/hw.hpp"
17 #include "vom/hw_cmds.hpp"
18 #include "vom/logger.hpp"
19
20 namespace VOM {
21 HW::cmd_q::cmd_q()
22   : m_enabled(true)
23   , m_connected(false)
24   , m_conn()
25 {
26 }
27
28 HW::cmd_q::~cmd_q()
29 {
30   m_connected = false;
31
32   if (m_rx_thread && m_rx_thread->joinable()) {
33     m_rx_thread->join();
34   }
35 }
36
37 HW::cmd_q&
38 HW::cmd_q::operator=(const HW::cmd_q& f)
39 {
40   return (*this);
41 }
42
43 /**
44  * Run the connect/dispatch thread.
45  */
46 void
47 HW::cmd_q::rx_run()
48 {
49   while (m_connected) {
50     m_conn.ctx().dispatch();
51   }
52 }
53
54 void
55 HW::cmd_q::enqueue(cmd* c)
56 {
57   std::shared_ptr<cmd> sp(c);
58
59   m_queue.push_back(sp);
60 }
61
62 void
63 HW::cmd_q::enqueue(std::shared_ptr<cmd> c)
64 {
65   m_queue.push_back(c);
66 }
67
68 void
69 HW::cmd_q::enqueue(std::queue<cmd*>& cmds)
70 {
71   while (cmds.size()) {
72     std::shared_ptr<cmd> sp(cmds.front());
73
74     m_queue.push_back(sp);
75     cmds.pop();
76   }
77 }
78
79 void
80 HW::cmd_q::dequeue(cmd* c)
81 {
82   c->retire(m_conn);
83   m_pending.erase(c);
84 }
85
86 void
87 HW::cmd_q::dequeue(std::shared_ptr<cmd> c)
88 {
89   c->retire(m_conn);
90   m_pending.erase(c.get());
91 }
92
93 void
94 HW::cmd_q::connect()
95 {
96   if (m_connected) {
97     m_conn.disconnect();
98   }
99
100   m_connected = false;
101
102   if (m_rx_thread && m_rx_thread->joinable()) {
103     m_rx_thread->join();
104   }
105
106   m_conn.connect();
107
108   m_connected = true;
109   m_rx_thread.reset(new std::thread(&HW::cmd_q::rx_run, this));
110 }
111
112 void
113 HW::cmd_q::enable()
114 {
115   m_enabled = true;
116 }
117
118 void
119 HW::cmd_q::disable()
120 {
121   m_enabled = false;
122 }
123
124 rc_t
125 HW::cmd_q::write()
126 {
127   rc_t rc = rc_t::OK;
128
129   /*
130    * The queue is enabled, Execute each command in the queue.
131    * If one execution fails, abort the rest
132    */
133   auto it = m_queue.begin();
134
135   while (it != m_queue.end()) {
136     std::shared_ptr<cmd> c = *it;
137
138     VOM_LOG(log_level_t::DEBUG) << *c;
139
140     if (m_enabled) {
141       /*
142        * before we issue the command we must move it to the pending
143        * store
144        * ince a async event can be recieved before the command
145        * completes
146        */
147       m_pending[c.get()] = c;
148
149       rc = c->issue(m_conn);
150
151       if (rc_t::INPROGRESS == rc) {
152         /*
153          * this command completes asynchronously
154          * leave the command in the pending store
155          */
156       } else {
157         /*
158          * the command completed, remove from the pending store
159          */
160         m_pending.erase(c.get());
161
162         if (rc_t::OK == rc) {
163           /*
164            * move to the next
165            */
166         } else {
167           /*
168            * barf out without issuing the rest
169            */
170           VOM_LOG(log_level_t::ERROR) << "Failed to execute: "
171                                       << c->to_string();
172           break;
173         }
174       }
175     } else {
176       /*
177        * The HW is disabled, so set each command as succeeded
178        */
179       c->succeeded();
180     }
181
182     ++it;
183   }
184
185   /*
186    * erase all objects in the queue
187    */
188   m_queue.erase(m_queue.begin(), m_queue.end());
189
190   return (rc);
191 }
192
193 /*
194  * The single Command Queue
195  */
196 HW::cmd_q* HW::m_cmdQ;
197 HW::item<bool> HW::m_poll_state;
198
199 /**
200  * Initialse the connection to VPP
201  */
202 void
203 HW::init(HW::cmd_q* f)
204 {
205   m_cmdQ = f;
206 }
207
208 /**
209  * Initialse the connection to VPP
210  */
211 void
212 HW::init()
213 {
214   m_cmdQ = new cmd_q();
215 }
216
217 void
218 HW::enqueue(cmd* cmd)
219 {
220   m_cmdQ->enqueue(cmd);
221 }
222
223 void
224 HW::enqueue(std::shared_ptr<cmd> cmd)
225 {
226   m_cmdQ->enqueue(cmd);
227 }
228
229 void
230 HW::enqueue(std::queue<cmd*>& cmds)
231 {
232   m_cmdQ->enqueue(cmds);
233 }
234
235 void
236 HW::dequeue(cmd* cmd)
237 {
238   m_cmdQ->dequeue(cmd);
239 }
240
241 void
242 HW::dequeue(std::shared_ptr<cmd> cmd)
243 {
244   m_cmdQ->dequeue(cmd);
245 }
246
247 void
248 HW::connect()
249 {
250   m_cmdQ->connect();
251 }
252
253 void
254 HW::enable()
255 {
256   m_cmdQ->enable();
257 }
258
259 void
260 HW::disable()
261 {
262   m_cmdQ->disable();
263 }
264
265 rc_t
266 HW::write()
267 {
268   return (m_cmdQ->write());
269 }
270
271 bool
272 HW::poll()
273 {
274   std::shared_ptr<cmd> poll(new hw_cmds::poll(m_poll_state));
275
276   HW::enqueue(poll);
277   HW::write();
278
279   return (m_poll_state);
280   return (true);
281 }
282
283 template <>
284 std::string
285 HW::item<bool>::to_string() const
286 {
287   std::ostringstream os;
288
289   os << "hw-item:["
290      << "rc:" << item_rc.to_string() << " data:" << item_data << "]";
291   return (os.str());
292 }
293
294 template <>
295 std::string
296 HW::item<unsigned int>::to_string() const
297 {
298   std::ostringstream os;
299
300   os << "hw-item:["
301      << "rc:" << item_rc.to_string() << " data:" << item_data << "]";
302   return (os.str());
303 }
304 }
305
306 /*
307  * fd.io coding-style-patch-verification: ON
308  *
309  * Local Variables:
310  * eval: (c-set-style "mozilla")
311  * End:
312  */