Line data Source code
1 : // DUNE DAQ modification notice:
2 : // This file has been modified from the original ATLAS system source for the DUNE DAQ project.
3 : // Fork baseline commit: system-00-00-20 (2020-09-25).
4 : // Renamed since fork: yes (from src/FIFOConnection.cxx to src/FIFOConnection.cpp).
5 :
6 : /*
7 : * FIFOConnection.cxx
8 : * OksSystem
9 : *
10 : * Created by Matthias Wiesmann on 07.04.05.
11 : * Copyright 2005 CERN. All rights reserved.
12 : *
13 : */
14 :
15 : #include <fcntl.h>
16 :
17 : #include "ers/ers.hpp"
18 :
19 : #include "okssystem/FIFOConnection.hpp"
20 : #include "okssystem/exceptions.hpp"
21 :
22 : const unsigned int OksSystem::FIFOConnection::MAX_MESSAGE_LEN = 512;
23 :
24 : /** Constructor, does not actually create the named pipe in the file okssystem.
25 : * To create it, use the \c make method
26 : * \param name the name (full path) of the named pipe
27 : */
28 :
29 0 : OksSystem::FIFOConnection::FIFOConnection(const std::string& name)
30 0 : : OksSystem::File(name)
31 : {
32 0 : m_fifo_fd = 0;
33 0 : m_is_blocking = true;
34 0 : }
35 :
36 : /** \overload */
37 :
38 0 : OksSystem::FIFOConnection::FIFOConnection(const File& file)
39 0 : : OksSystem::File(file)
40 : {
41 0 : m_fifo_fd = 0;
42 0 : m_is_blocking = true;
43 0 : }
44 :
45 0 : OksSystem::FIFOConnection::~FIFOConnection()
46 : {
47 0 : delete m_fifo_fd;
48 0 : }
49 :
50 : void
51 0 : OksSystem::FIFOConnection::make(mode_t perm) const
52 : {
53 0 : File::make_fifo(perm);
54 0 : } // make
55 :
56 : /** Blocking read of a single message (string) from a FIFO
57 : * \return the actual message
58 : * \note maximum message length is MAX_MESSAGE_LEN-1 bytes
59 : */
60 :
61 : std::string
62 0 : OksSystem::FIFOConnection::read_message() const
63 : {
64 0 : ERS_ASSERT_MSG(exists(), "FIFO " << c_full_name() << " does not exist.");
65 0 : if (!is_fifo()) {
66 0 : ers::warning(OksSystem::Exception(ERS_HERE, std::string(c_full_name()) + std::string(" is not a FIFO")));
67 : } // should probably be FIFO
68 0 : OksSystem::Descriptor connection_fd(this, O_RDONLY, 0);
69 0 : char buffer[MAX_MESSAGE_LEN];
70 0 : while (true) {
71 0 : const int status = connection_fd.read(buffer, sizeof(buffer) - 1);
72 0 : if (status > 0) {
73 0 : ERS_ASSERT(status < (int)sizeof(buffer));
74 0 : buffer[status] = '\0'; // we make sure we have a C-string
75 0 : return std::string(buffer);
76 : } // if
77 0 : usleep(100000);
78 : } // while
79 0 : } // read_message
80 :
81 : void
82 0 : OksSystem::FIFOConnection::send_message(const std::string& message) const
83 : {
84 0 : ERS_ASSERT_MSG(exists(), "FIFO " << c_full_name() << " does not exist. Cannot put " << message << " into FIFO.");
85 0 : if (!is_fifo()) {
86 0 : ers::warning(OksSystem::Exception(ERS_HERE, std::string(c_full_name()) + std::string(" is not a FIFO")));
87 : } // should probably be FIFO
88 0 : const unsigned int l = message.size();
89 0 : ERS_RANGE_CHECK(1, l, MAX_MESSAGE_LEN);
90 0 : OksSystem::Descriptor connection_fd(this, O_WRONLY, 0);
91 0 : connection_fd.write(message.data(), l);
92 0 : } // send_message
93 :
94 : /**
95 : * \brief It writes a message to a FIFO.
96 : * \param message The message to write into the FIFO.
97 : * \note \li The maximum message length is MAX_MESSAGE_LEN-1 bytes.
98 : * \li This method does not take care of opening the FIFO (as it happens in send_message()),
99 : * and should be used only when the FIFO is opened using one of the open_w() or
100 : * open_wr() methods (see linux "open", "fifo" and "write" man/info pages for more details).
101 : * \li This method will block or not depending on the way the FIFO has been opened.
102 : */
103 :
104 : void
105 0 : OksSystem::FIFOConnection::send(const std::string& message) const
106 : {
107 0 : ERS_ASSERT(m_fifo_fd);
108 0 : const unsigned int l = message.size();
109 0 : ERS_RANGE_CHECK(1, l, MAX_MESSAGE_LEN);
110 0 : m_fifo_fd->write(message.data(), l);
111 0 : } // send
112 :
113 : /**
114 : * \brief It reads a single message (string) from a FIFO.
115 : * \return The actual message.
116 : * \note \li The maximum message length is MAX_MESSAGE_LEN-1 bytes.
117 : * \li This method does not take care of opening the FIFO (as it happens in read_message()),
118 : * and should be used only when the FIFO is opened using one of the open_r() or
119 : * open_wr() methods (see linux "open", "fifo" and "read" man/info pages for more details).
120 : * \li This method will block or not depending on the way the FIFO has been opened.
121 : */
122 :
123 : std::string
124 0 : OksSystem::FIFOConnection::read() const
125 : {
126 0 : ERS_ASSERT(m_fifo_fd);
127 0 : char buffer[MAX_MESSAGE_LEN];
128 0 : while (true) {
129 0 : const int status = m_fifo_fd->read(buffer, sizeof(buffer) - 1);
130 0 : if (status > 0) {
131 0 : ERS_ASSERT(status < (int)sizeof(buffer));
132 0 : buffer[status] = '\0'; // we make sure we have a C-string
133 0 : return std::string(buffer);
134 : } // if
135 0 : if (m_is_blocking == false && status == 0)
136 0 : return std::string("");
137 0 : usleep(100000); // Slow down the loop
138 : } // while
139 : } // read
140 :
141 : /**
142 : * \brief It opens the FIFO in read-only mode.
143 : * \return A pointer to a OksSystem::Descriptor object holding the FIFO file descriptor.
144 : * \param block If \c TRUE the FIFO will be opened in blocking mode.
145 : */
146 :
147 : OksSystem::Descriptor*
148 0 : OksSystem::FIFOConnection::open_r(bool block)
149 : {
150 :
151 0 : ERS_ASSERT(!m_fifo_fd);
152 :
153 0 : int flags = O_RDONLY;
154 :
155 0 : if (block == false) {
156 0 : flags = O_RDONLY | O_NONBLOCK;
157 0 : m_is_blocking = false;
158 : }
159 :
160 0 : try {
161 0 : m_fifo_fd = new OksSystem::Descriptor(this, flags, 0);
162 0 : } catch (OksSystem::OpenFileIssue& ex) {
163 0 : delete m_fifo_fd;
164 0 : m_fifo_fd = 0;
165 0 : throw;
166 0 : }
167 :
168 0 : return m_fifo_fd;
169 : }
170 :
171 : /**
172 : * \brief It opens the FIFO in write-only mode.
173 : * \return A pointer to a OksSystem::Descriptor object holding the FIFO file descriptor.
174 : * \param block If \c TRUE the FIFO will be opened in blocking mode.
175 : */
176 :
177 : OksSystem::Descriptor*
178 0 : OksSystem::FIFOConnection::open_w(bool block)
179 : {
180 :
181 0 : ERS_ASSERT(!m_fifo_fd);
182 :
183 0 : int flags = O_WRONLY;
184 :
185 0 : if (block == false) {
186 0 : flags = O_WRONLY | O_NONBLOCK;
187 0 : m_is_blocking = false;
188 : }
189 :
190 0 : try {
191 0 : m_fifo_fd = new OksSystem::Descriptor(this, flags, 0);
192 0 : } catch (OksSystem::OpenFileIssue& ex) {
193 0 : delete m_fifo_fd;
194 0 : m_fifo_fd = 0;
195 0 : throw;
196 0 : }
197 :
198 0 : return m_fifo_fd;
199 : }
200 :
201 : /**
202 : * \brief It opens the FIFO in read and write mode.
203 : * \return A pointer to a OksSystem::Descriptor object holding the FIFO file descriptor.
204 : * \param block If \c TRUE the FIFO will be opened in blocking mode.
205 : */
206 :
207 : OksSystem::Descriptor*
208 0 : OksSystem::FIFOConnection::open_rw(bool block)
209 : {
210 :
211 0 : ERS_ASSERT(!m_fifo_fd);
212 :
213 0 : int flags = O_RDWR;
214 :
215 0 : if (block == false) {
216 0 : flags = O_RDWR | O_NONBLOCK;
217 0 : m_is_blocking = false;
218 : }
219 :
220 0 : try {
221 0 : m_fifo_fd = new OksSystem::Descriptor(this, flags, 0);
222 0 : } catch (OksSystem::OpenFileIssue& ex) {
223 0 : delete m_fifo_fd;
224 0 : m_fifo_fd = 0;
225 0 : throw;
226 0 : }
227 :
228 0 : return m_fifo_fd;
229 : }
230 :
231 : /**
232 : * \brief It closes the FIFO file descriptor.
233 : * \note This method has to be used to close the FIFO file descriptor only when
234 : * it is opened using one of the open_r(), open_w() or open_wr() methods.
235 : */
236 :
237 : void
238 0 : OksSystem::FIFOConnection::close()
239 : {
240 :
241 0 : delete m_fifo_fd;
242 0 : m_fifo_fd = 0;
243 0 : }
244 :
245 : /**
246 : * \brief It gets the FIFO file descriptor.
247 : * \note This method can to be used only when the FIFO
248 : * is opened using the open_r(), open_w() or open_rw() methods.
249 : * \return The FIFO file descriptor.
250 : */
251 :
252 : int
253 0 : OksSystem::FIFOConnection::fd() const
254 : {
255 :
256 0 : ERS_ASSERT(m_fifo_fd);
257 0 : return m_fifo_fd->fd();
258 : }
|