Line data Source code
1 :
2 : /* Copyright (c) 2005-2012, Stefan Eilemann <eile@equalizergraphics.com>
3 : *
4 : * This file is part of Collage <https://github.com/Eyescale/Collage>
5 : *
6 : * This library is free software; you can redistribute it and/or modify it under
7 : * the terms of the GNU Lesser General Public License version 2.1 as published
8 : * by the Free Software Foundation.
9 : *
10 : * This library is distributed in the hope that it will be useful, but WITHOUT
11 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 : * details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public License
16 : * along with this library; if not, write to the Free Software Foundation, Inc.,
17 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 : */
19 :
20 : #include "fdConnection.h"
21 :
22 : #include "connectionDescription.h"
23 : #include "exception.h"
24 : #include "global.h"
25 : #include "log.h"
26 :
27 : #include <lunchbox/os.h>
28 :
29 : #include <errno.h>
30 : #include <poll.h>
31 :
32 : namespace co
33 : {
34 366 : FDConnection::FDConnection()
35 : : _readFD( 0 ),
36 366 : _writeFD( 0 )
37 367 : {}
38 :
39 38 : int FDConnection::_getTimeOut()
40 : {
41 38 : const uint32_t timeout = Global::getTimeout();
42 38 : return timeout == LB_TIMEOUT_INDEFINITE ? -1 : int( timeout );
43 : }
44 :
45 : //----------------------------------------------------------------------
46 : // read
47 : //----------------------------------------------------------------------
48 2069511 : int64_t FDConnection::readSync( void* buffer, const uint64_t bytes, const bool )
49 : {
50 2069511 : if( _readFD < 1 )
51 0 : return -1;
52 :
53 2069511 : ssize_t bytesRead = ::read( _readFD, buffer, bytes );
54 2069511 : if( bytesRead > 0 )
55 2069473 : return bytesRead;
56 :
57 38 : if( bytesRead == 0 || errno == EWOULDBLOCK || errno == EAGAIN )
58 : {
59 : struct pollfd fds[1];
60 38 : fds[0].fd = _readFD;
61 38 : fds[0].events = POLLIN;
62 :
63 38 : const int res = poll( fds, 1, _getTimeOut( ));
64 38 : if( res < 0 )
65 : {
66 0 : LBWARN << "Error during read : " << strerror( errno ) << std::endl;
67 0 : return -1;
68 : }
69 :
70 38 : if( res == 0 )
71 0 : throw Exception( Exception::TIMEOUT_READ );
72 :
73 38 : bytesRead = ::read( _readFD, buffer, bytes );
74 : }
75 :
76 38 : if( bytesRead > 0 )
77 0 : return bytesRead;
78 :
79 38 : if( bytesRead == 0 ) // EOF
80 : {
81 190 : LBDEBUG << "Got EOF, closing " << getDescription()->toString()
82 152 : << std::endl;
83 38 : close();
84 38 : return -1;
85 : }
86 :
87 0 : LBASSERT( bytesRead == -1 ); // error
88 :
89 0 : if( errno == EINTR ) // if interrupted, try again
90 0 : return 0;
91 :
92 0 : LBWARN << "Error during read: " << strerror( errno ) << ", " << bytes
93 0 : << "b on fd " << _readFD << std::endl;
94 0 : return -1;
95 : }
96 :
97 : //----------------------------------------------------------------------
98 : // write
99 : //----------------------------------------------------------------------
100 2033478 : int64_t FDConnection::write( const void* buffer, const uint64_t bytes )
101 : {
102 2033478 : if( !isConnected() || _writeFD < 1 )
103 0 : return -1;
104 :
105 2032090 : ssize_t bytesWritten = ::write( _writeFD, buffer, bytes );
106 2027769 : if( bytesWritten > 0 )
107 2027769 : return bytesWritten;
108 :
109 0 : if( bytesWritten == 0 || errno == EWOULDBLOCK || errno == EAGAIN )
110 : {
111 : struct pollfd fds[1];
112 0 : fds[0].fd = _writeFD;
113 0 : fds[0].events = POLLOUT;
114 0 : const int res = poll( fds, 1, _getTimeOut( ));
115 0 : if (res < 0)
116 : {
117 0 : LBWARN << "Write error: " << lunchbox::sysError << std::endl;
118 0 : return -1;
119 : }
120 :
121 0 : if( res == 0)
122 0 : throw Exception( Exception::TIMEOUT_WRITE );
123 :
124 0 : bytesWritten = ::write( _writeFD, buffer, bytes );
125 : }
126 :
127 0 : if( bytesWritten > 0 )
128 0 : return bytesWritten;
129 :
130 0 : if( bytesWritten == -1 ) // error
131 : {
132 0 : if( errno == EINTR ) // if interrupted, try again
133 0 : return 0;
134 :
135 0 : LBWARN << "Error during write: " << lunchbox::sysError << std::endl;
136 0 : return -1;
137 : }
138 :
139 0 : return bytesWritten;
140 : }
141 66 : }
|