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) : OksSystem::File(name) {
30 0 : m_fifo_fd = 0;
31 0 : m_is_blocking = true;
32 0 : }
33 :
34 : /** \overload */
35 :
36 0 : OksSystem::FIFOConnection::FIFOConnection(const File &file) : OksSystem::File(file) {
37 0 : m_fifo_fd = 0;
38 0 : m_is_blocking = true;
39 0 : }
40 :
41 0 : OksSystem::FIFOConnection::~FIFOConnection() {
42 0 : delete m_fifo_fd;
43 0 : }
44 :
45 0 : void OksSystem::FIFOConnection::make(mode_t perm) const {
46 0 : File::make_fifo(perm);
47 0 : } // make
48 :
49 : /** Blocking read of a single message (string) from a FIFO
50 : * \return the actual message
51 : * \note maximum message length is MAX_MESSAGE_LEN-1 bytes
52 : */
53 :
54 0 : std::string OksSystem::FIFOConnection::read_message() const {
55 0 : ERS_ASSERT_MSG(exists(),"FIFO "<< c_full_name() << " does not exist.");
56 0 : if (! is_fifo()) {
57 0 : ers::warning(OksSystem::Exception(ERS_HERE, std::string(c_full_name()) + std::string(" is not a FIFO")));
58 : } // should probably be FIFO
59 0 : OksSystem::Descriptor connection_fd(this,O_RDONLY,0);
60 0 : char buffer[MAX_MESSAGE_LEN];
61 0 : while(true) {
62 0 : const int status = connection_fd.read(buffer,sizeof(buffer)-1);
63 0 : if (status>0) {
64 0 : ERS_ASSERT(status<(int) sizeof(buffer));
65 0 : buffer[status] = '\0';// we make sure we have a C-string
66 0 : return std::string(buffer);
67 : } // if
68 0 : usleep(100000);
69 : } // while
70 0 : } // read_message
71 :
72 0 : void OksSystem::FIFOConnection::send_message(const std::string &message) const {
73 0 : ERS_ASSERT_MSG(exists(),"FIFO "<< c_full_name() << " does not exist. Cannot put "<< message << " into FIFO.");
74 0 : if (! is_fifo()) {
75 0 : ers::warning(OksSystem::Exception(ERS_HERE, std::string(c_full_name()) + std::string(" is not a FIFO")));
76 : } // should probably be FIFO
77 0 : const unsigned int l = message.size();
78 0 : ERS_RANGE_CHECK(1,l,MAX_MESSAGE_LEN);
79 0 : OksSystem::Descriptor connection_fd(this,O_WRONLY,0);
80 0 : connection_fd.write(message.data(),l);
81 0 : } // send_message
82 :
83 : /**
84 : * \brief It writes a message to a FIFO.
85 : * \param message The message to write into the FIFO.
86 : * \note \li The maximum message length is MAX_MESSAGE_LEN-1 bytes.
87 : * \li This method does not take care of opening the FIFO (as it happens in send_message()),
88 : * and should be used only when the FIFO is opened using one of the open_w() or
89 : * open_wr() methods (see linux "open", "fifo" and "write" man/info pages for more details).
90 : * \li This method will block or not depending on the way the FIFO has been opened.
91 : */
92 :
93 0 : void OksSystem::FIFOConnection::send(const std::string &message) const {
94 0 : ERS_ASSERT(m_fifo_fd);
95 0 : const unsigned int l = message.size();
96 0 : ERS_RANGE_CHECK(1,l,MAX_MESSAGE_LEN);
97 0 : m_fifo_fd->write(message.data(),l);
98 0 : } // send
99 :
100 : /**
101 : * \brief It reads a single message (string) from a FIFO.
102 : * \return The actual message.
103 : * \note \li The maximum message length is MAX_MESSAGE_LEN-1 bytes.
104 : * \li This method does not take care of opening the FIFO (as it happens in read_message()),
105 : * and should be used only when the FIFO is opened using one of the open_r() or
106 : * open_wr() methods (see linux "open", "fifo" and "read" man/info pages for more details).
107 : * \li This method will block or not depending on the way the FIFO has been opened.
108 : */
109 :
110 0 : std::string OksSystem::FIFOConnection::read() const {
111 0 : ERS_ASSERT(m_fifo_fd);
112 0 : char buffer[MAX_MESSAGE_LEN];
113 0 : while(true) {
114 0 : const int status = m_fifo_fd->read(buffer,sizeof(buffer)-1);
115 0 : if (status>0) {
116 0 : ERS_ASSERT(status<(int) sizeof(buffer));
117 0 : buffer[status] = '\0';// we make sure we have a C-string
118 0 : return std::string(buffer);
119 : } // if
120 0 : if (m_is_blocking == false && status == 0) return std::string("");
121 0 : usleep(100000); // Slow down the loop
122 : } // while
123 : } // read
124 :
125 : /**
126 : * \brief It opens the FIFO in read-only mode.
127 : * \return A pointer to a OksSystem::Descriptor object holding the FIFO file descriptor.
128 : * \param block If \c TRUE the FIFO will be opened in blocking mode.
129 : */
130 :
131 0 : OksSystem::Descriptor* OksSystem::FIFOConnection::open_r(bool block) {
132 :
133 0 : ERS_ASSERT(!m_fifo_fd);
134 :
135 0 : int flags = O_RDONLY;
136 :
137 0 : if(block == false) {
138 0 : flags = O_RDONLY|O_NONBLOCK;
139 0 : m_is_blocking = false;
140 : }
141 :
142 0 : try {
143 0 : m_fifo_fd = new OksSystem::Descriptor(this,flags,0);
144 : }
145 0 : catch(OksSystem::OpenFileIssue &ex) {
146 0 : delete m_fifo_fd;
147 0 : m_fifo_fd = 0;
148 0 : throw;
149 0 : }
150 :
151 0 : return m_fifo_fd;
152 :
153 : }
154 :
155 : /**
156 : * \brief It opens the FIFO in write-only mode.
157 : * \return A pointer to a OksSystem::Descriptor object holding the FIFO file descriptor.
158 : * \param block If \c TRUE the FIFO will be opened in blocking mode.
159 : */
160 :
161 :
162 0 : OksSystem::Descriptor* OksSystem::FIFOConnection::open_w(bool block) {
163 :
164 0 : ERS_ASSERT(!m_fifo_fd);
165 :
166 0 : int flags = O_WRONLY;
167 :
168 0 : if(block == false) {
169 0 : flags = O_WRONLY|O_NONBLOCK;
170 0 : m_is_blocking = false;
171 : }
172 :
173 0 : try {
174 0 : m_fifo_fd = new OksSystem::Descriptor(this,flags,0);
175 : }
176 0 : catch(OksSystem::OpenFileIssue &ex) {
177 0 : delete m_fifo_fd;
178 0 : m_fifo_fd = 0;
179 0 : throw;
180 0 : }
181 :
182 0 : return m_fifo_fd;
183 :
184 : }
185 :
186 : /**
187 : * \brief It opens the FIFO in read and write mode.
188 : * \return A pointer to a OksSystem::Descriptor object holding the FIFO file descriptor.
189 : * \param block If \c TRUE the FIFO will be opened in blocking mode.
190 : */
191 :
192 0 : OksSystem::Descriptor* OksSystem::FIFOConnection::open_rw(bool block) {
193 :
194 0 : ERS_ASSERT(!m_fifo_fd);
195 :
196 0 : int flags = O_RDWR;
197 :
198 0 : if(block == false) {
199 0 : flags = O_RDWR|O_NONBLOCK;
200 0 : m_is_blocking = false;
201 : }
202 :
203 0 : try {
204 0 : m_fifo_fd = new OksSystem::Descriptor(this,flags,0);
205 : }
206 0 : catch(OksSystem::OpenFileIssue &ex) {
207 0 : delete m_fifo_fd;
208 0 : m_fifo_fd = 0;
209 0 : throw;
210 0 : }
211 :
212 0 : return m_fifo_fd;
213 :
214 : }
215 :
216 : /**
217 : * \brief It closes the FIFO file descriptor.
218 : * \note This method has to be used to close the FIFO file descriptor only when
219 : * it is opened using one of the open_r(), open_w() or open_wr() methods.
220 : */
221 :
222 0 : void OksSystem::FIFOConnection::close() {
223 :
224 0 : delete m_fifo_fd;
225 0 : m_fifo_fd = 0;
226 :
227 0 : }
228 :
229 : /**
230 : * \brief It gets the FIFO file descriptor.
231 : * \note This method can to be used only when the FIFO
232 : * is opened using the open_r(), open_w() or open_rw() methods.
233 : * \return The FIFO file descriptor.
234 : */
235 :
236 0 : int OksSystem::FIFOConnection::fd() const {
237 :
238 0 : ERS_ASSERT(m_fifo_fd);
239 0 : return m_fifo_fd->fd();
240 :
241 : }
|