w11 - cpp 0.794
Backend server for Rlink and w11
Loading...
Searching...
No Matches
RlinkPort.cpp
Go to the documentation of this file.
1// $Id: RlinkPort.cpp 1186 2019-07-12 17:49:59Z mueller $
2// SPDX-License-Identifier: GPL-3.0-or-later
3// Copyright 2011-2018 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4//
5// Revision History:
6// Date Rev Version Comment
7// 2018-12-19 1090 1.4.4 use RosPrintf(bool)
8// 2018-12-18 1089 1.4.3 use c++ style casts
9// 2017-04-29 888 1.4.2 BUGFIX: RawRead(): proper irc for exactsize=false
10// 2017-04-07 868 1.4.1 Dump(): add detail arg
11// 2017-02-19 853 1.4 use Rtime, drop TimeOfDayAsDouble
12// 2015-04-11 666 1.3 add fXon, XonEnable()
13// 2014-12-10 611 1.2.4 add time stamps for Read/Write for logs
14// 2014-11-29 607 1.2.3 BUGFIX: fix time handling on RawRead()
15// 2014-11-23 606 1.2.2 use Rtools::TimeOfDayAsDouble()
16// 2014-08-22 584 1.2.1 use nullptr
17// 2013-02-23 492 1.2 use RparseUrl
18// 2013-02-22 491 1.1 use new RlogFile/RlogMsg interfaces
19// 2013-02-10 485 1.0.5 add static const defs
20// 2013-02-03 481 1.0.4 use Rexception
21// 2013-01-27 477 1.0.3 add RawRead(),RawWrite() methods
22// 2012-12-28 466 1.0.2 allow Close() even when not open
23// 2012-12-26 465 1.0.1 add CloseFd() method
24// 2011-03-27 375 1.0 Initial version
25// 2011-01-15 356 0.1 First draft
26// ---------------------------------------------------------------------------
27
32#include <errno.h>
33#include <unistd.h>
34#include <poll.h>
35
36#include <iostream>
37
38#include "librtools/RosFill.hpp"
42#include "librtools/RlogMsg.hpp"
43#include "librtools/Rtools.hpp"
44
45#include "RlinkPort.hpp"
46
47using namespace std;
48
54// all method definitions in namespace Retro
55namespace Retro {
56
57//------------------------------------------+-----------------------------------
58// constants definitions
59
60const int RlinkPort::kEof;
61const int RlinkPort::kTout;
62const int RlinkPort::kErr;
63
64//------------------------------------------+-----------------------------------
66
68 : fIsOpen(false),
69 fUrl(),
70 fXon(false),
71 fFdRead(-1),
72 fFdWrite(-1),
73 fspLog(),
74 fTraceLevel(0),
75 fTsLastRead(),
76 fTsLastWrite(),
77 fStats()
78{
79 fStats.Define(kStatNPortWrite, "NPortWrite", "Port::Write() calls");
80 fStats.Define(kStatNPortRead, "NPortRead", "Port::Read() calls");
81 fStats.Define(kStatNPortTxByt, "NPortTxByt", "Port Tx bytes send");
82 fStats.Define(kStatNPortRxByt, "NPortRxByt", "Port Rx bytes rcvd");
83 fStats.Define(kStatNPortRawWrite, "NPortRawWrite", "Port::RawWrite() calls");
84 fStats.Define(kStatNPortRawRead, "NPortRawRead", "Port::RawRead() calls");
85}
86
87//------------------------------------------+-----------------------------------
89
91{
92 if (IsOpen()) RlinkPort::Close();
93}
94
95//------------------------------------------+-----------------------------------
97
99{
100 if (!IsOpen()) return;
101
102 if (fFdWrite == fFdRead) fFdWrite = -1;
105
106 fIsOpen = false;
107 fUrl.Clear();
108
109 return;
110}
111
112//------------------------------------------+-----------------------------------
114
115int RlinkPort::Read(uint8_t* buf, size_t size, const Rtime& timeout,
116 RerrMsg& emsg)
117{
118 if (!IsOpen())
119 throw Rexception("RlinkPort::Read()","Bad state: port not open");
120 if (buf == nullptr)
121 throw Rexception("RlinkPort::Read()","Bad args: buf==nullptr");
122 if (size == 0)
123 throw Rexception("RlinkPort::Read()","Bad args: size==0");
124
126
127 bool rdpoll = PollRead(timeout);
128 if (!rdpoll) return kTout;
129
130 int irc = -1;
131 while (irc < 0) {
132 irc = ::read(fFdRead, buf, size);
133 if (irc < 0 && errno != EINTR) {
134 emsg.InitErrno("RlinkPort::Read()", "read() failed : ", errno);
135 if (fspLog && fTraceLevel>0) fspLog->Write(emsg.Message(), 'E');
136 return kErr;
137 }
138 }
139
140 if (fspLog && fTraceLevel>0) {
141 RlogMsg lmsg(*fspLog, 'I');
142 lmsg << "port read nchar=" << RosPrintf(irc,"d",4);
143 Rtime now(CLOCK_MONOTONIC);
144 if (fTsLastRead.IsPositive())
145 lmsg << " dt_rd=" << RosPrintf(double(now-fTsLastRead),"f",8,6);
147 lmsg << " dt_wr=" << RosPrintf(double(now-fTsLastWrite),"f",8,6);
148 fTsLastRead = now;
149 if (fTraceLevel>1) {
150 size_t ncol = (80-5-6)/(2+1);
151 for (int i=0; i<irc; i++) {
152 if ((i%ncol)==0) lmsg << "\n " << RosPrintf(i,"d",4) << ": ";
153 lmsg << RosPrintBvi(buf[i],16) << " ";
154 }
155 }
156 }
157
158 fStats.Inc(kStatNPortRxByt, double(irc));
159
160 return irc;
161}
162
163//------------------------------------------+-----------------------------------
165
166int RlinkPort::Write(const uint8_t* buf, size_t size, RerrMsg& emsg)
167{
168 if (!IsOpen())
169 throw Rexception("RlinkPort::Write()","Bad state: port not open");
170 if (buf == nullptr)
171 throw Rexception("RlinkPort::Write()","Bad args: buf==nullptr");
172 if (size == 0)
173 throw Rexception("RlinkPort::Write()","Bad args: size==0");
174
176
177 if (fspLog && fTraceLevel>0) {
178 RlogMsg lmsg(*fspLog, 'I');
179 lmsg << "port write nchar=" << RosPrintf(size,"d",4);
180 Rtime now(CLOCK_MONOTONIC);
181 if (fTsLastRead.IsPositive())
182 lmsg << " dt_rd=" << RosPrintf(double(now-fTsLastRead),"f",8,6);
184 lmsg << " dt_wr=" << RosPrintf(double(now-fTsLastWrite),"f",8,6);
185 fTsLastWrite = now;
186 if (fTraceLevel>1) {
187 size_t ncol = (80-5-6)/(2+1);
188 for (size_t i=0; i<size; i++) {
189 if ((i%ncol)==0) lmsg << "\n " << RosPrintf(i,"d",4) << ": ";
190 lmsg << RosPrintBvi(buf[i],16) << " ";
191 }
192 }
193 }
194
195 size_t ndone = 0;
196 while (ndone < size) {
197 int irc = -1;
198 while (irc < 0) {
199 irc = ::write(fFdWrite, buf+ndone, size-ndone);
200 if (irc < 0 && errno != EINTR) {
201 emsg.InitErrno("RlinkPort::Write()", "write() failed : ", errno);
202 if (fspLog && fTraceLevel>0) fspLog->Write(emsg.Message(), 'E');
203 return kErr;
204 }
205 }
206 // FIXME_code: handle eof ??
207 ndone += irc;
208 }
209
210 fStats.Inc(kStatNPortTxByt, double(ndone));
211
212 return ndone;
213}
214
215//------------------------------------------+-----------------------------------
217
218bool RlinkPort::PollRead(const Rtime& timeout)
219{
220 if (! IsOpen())
221 throw Rexception("RlinkPort::PollRead()","Bad state: port not open");
222 if (timeout.IsNegative())
223 throw Rexception("RlinkPort::PollRead()","Bad args: timeout < 0");
224
225 int ito = timeout.ToMSec();
226
227 struct pollfd fds[1] = {{fFdRead, // fd
228 POLLIN, // events
229 0}}; // revents
230
231
232 int irc = -1;
233 while (irc < 0) {
234 irc = ::poll(fds, 1, ito);
235 if (irc < 0 && errno != EINTR)
236 throw Rexception("RlinkPort::PollRead()","poll() failed: rc<0: ", errno);
237 }
238
239 if (irc == 0) return false;
240
241 if (fds[0].revents == POLLERR)
242 throw Rexception("RlinkPort::PollRead()", "poll() failed: POLLERR");
243
244 return true;
245}
246
247//------------------------------------------+-----------------------------------
249int RlinkPort::RawRead(uint8_t* buf, size_t size, bool exactsize,
250 const Rtime& timeout, Rtime& tused, RerrMsg& emsg)
251{
252 if (!timeout.IsPositive())
253 throw Rexception("RlinkPort::RawRead()", "Bad args: timeout <= 0.");
254 if (size <= 0)
255 throw Rexception("RlinkPort::RawRead()", "Bad args: size <= 0");
256
258 tused.Clear();
259
260 Rtime tnow(CLOCK_MONOTONIC);
261 Rtime tend = tnow + timeout;
262 Rtime tbeg = tnow;
263
264 size_t ndone = 0;
265 while (tnow < tend && ndone<size) {
266 int irc = Read(buf+ndone, size-ndone, tend-tnow, emsg);
267 tnow.GetClock(CLOCK_MONOTONIC);
268 tused = tnow - tbeg;
269 if (irc <= 0) return irc;
270 ndone += irc;
271 if (!exactsize) break;
272 }
273
274 return int(ndone);
275}
276
277//------------------------------------------+-----------------------------------
279int RlinkPort::RawWrite(const uint8_t* buf, size_t size, RerrMsg& emsg)
280{
282 return Write(buf, size, emsg);
283}
284
285//------------------------------------------+-----------------------------------
287
288void RlinkPort::Dump(std::ostream& os, int ind, const char* text,
289 int detail) const
290{
291 RosFill bl(ind);
292 os << bl << (text?text:"--") << "RlinkPort @ " << this << endl;
293
294 os << bl << " fIsOpen: " << RosPrintf(fIsOpen) << endl;
295 fUrl.Dump(os, ind+2, "fUrl: ");
296 os << bl << " fXon: " << RosPrintf(fXon) << endl;
297 os << bl << " fFdRead: " << fFdRead << endl;
298 os << bl << " fFdWrite: " << fFdWrite << endl;
299 os << bl << " fspLog: " << fspLog.get() << endl;
300 os << bl << " fTraceLevel: " << fTraceLevel << endl;
301 os << bl << " fTsLastRead: " << fTsLastRead << endl;
302 os << bl << " fTsLastWrite: " << fTsLastWrite << endl;
303 fStats.Dump(os, ind+2, "fStats: ", detail);
304 return;
305}
306
307//------------------------------------------+-----------------------------------
309
311{
312 if (fd >= 0) {
313 ::close(fd);
314 fd = -1;
315 }
316 return;
317}
318
319} // end namespace Retro
FIXME_docs.
Definition: RerrMsg.hpp:25
std::string Message() const
FIXME_docs.
Definition: RerrMsg.cpp:161
void InitErrno(const std::string &meth, const std::string &text, int errnum)
FIXME_docs.
Definition: RerrMsg.cpp:84
FIXME_docs.
Definition: Rexception.hpp:29
int RawRead(uint8_t *buf, size_t size, bool exactsize, const Rtime &timeout, Rtime &tused, RerrMsg &emsg)
FIXME_docs.
Definition: RlinkPort.cpp:249
int RawWrite(const uint8_t *buf, size_t size, RerrMsg &emsg)
FIXME_docs.
Definition: RlinkPort.cpp:279
virtual bool PollRead(const Rtime &timeout)
FIXME_docs.
Definition: RlinkPort.cpp:218
Rtime fTsLastWrite
time stamp last write
Definition: RlinkPort.hpp:113
static const int kEof
return code: end-of-file
Definition: RlinkPort.hpp:86
void CloseFd(int &fd)
FIXME_docs.
Definition: RlinkPort.cpp:310
int fFdWrite
fd for write
Definition: RlinkPort.hpp:109
bool IsOpen() const
FIXME_docs.
Definition: RlinkPort.ipp:27
RparseUrl fUrl
parsed url
Definition: RlinkPort.hpp:106
virtual ~RlinkPort()
Destructor.
Definition: RlinkPort.cpp:90
int fFdRead
fd for read
Definition: RlinkPort.hpp:108
bool fIsOpen
is open flag
Definition: RlinkPort.hpp:105
static const int kErr
return code: IO error
Definition: RlinkPort.hpp:88
RlinkPort()
Default constructor.
Definition: RlinkPort.cpp:67
std::shared_ptr< RlogFile > fspLog
log file ptr
Definition: RlinkPort.hpp:110
bool fXon
xon attribute set
Definition: RlinkPort.hpp:107
static const int kTout
return code: time out
Definition: RlinkPort.hpp:87
virtual int Read(uint8_t *buf, size_t size, const Rtime &timeout, RerrMsg &emsg)
FIXME_docs.
Definition: RlinkPort.cpp:115
virtual void Close()
FIXME_docs.
Definition: RlinkPort.cpp:98
virtual int Write(const uint8_t *buf, size_t size, RerrMsg &emsg)
FIXME_docs.
Definition: RlinkPort.cpp:166
Rtime fTsLastRead
time stamp last write
Definition: RlinkPort.hpp:112
Rstats fStats
statistics
Definition: RlinkPort.hpp:114
virtual void Dump(std::ostream &os, int ind=0, const char *text=0, int detail=0) const
FIXME_docs.
Definition: RlinkPort.cpp:288
uint32_t fTraceLevel
trace level
Definition: RlinkPort.hpp:111
FIXME_docs.
Definition: RlogMsg.hpp:24
I/O appicator to generate fill characters.
Definition: RosFill.hpp:24
virtual void Dump(std::ostream &os, int ind=0, const char *text=0) const
FIXME_docs.
Definition: RparseUrl.cpp:219
void Clear()
FIXME_docs.
Definition: RparseUrl.cpp:144
void Dump(std::ostream &os, int ind=0, const char *text=0, int detail=0) const
FIXME_docs.
Definition: Rstats.cpp:178
void Inc(size_t ind, double val=1.)
FIXME_docs.
Definition: Rstats.ipp:29
void Define(size_t ind, const std::string &name, const std::string &text)
FIXME_docs.
Definition: Rstats.cpp:72
FIXME_docs.
Definition: Rtime.hpp:25
bool IsNegative() const
FIXME_docs.
Definition: Rtime.ipp:101
int ToMSec() const
FIXME_docs.
Definition: Rtime.ipp:133
bool IsPositive() const
FIXME_docs.
Definition: Rtime.ipp:93
void Clear()
FIXME_docs.
Definition: Rtime.ipp:76
void GetClock(clockid_t clkid)
FIXME_docs.
Definition: Rtime.cpp:41
RosPrintfS< bool > RosPrintf(bool value, const char *form=0, int width=0, int prec=0)
Creates a print object for the formatted output of a bool value.
Definition: RosPrintf.ipp:38
Declaration of class ReventLoop.
Definition: ReventLoop.cpp:47