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