~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/mysql_protocol/vio.cc

  • Committer: Brian Aker
  • Date: 2010-07-16 05:40:08 UTC
  • mto: This revision was merged to the branch mainline in revision 1661.
  • Revision ID: brian@gaz-20100716054008-cfcvyu0akpwqnwqd
Encapsulate Table in field

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
/*
17
17
  Note that we can't have assertion on file descriptors;  The reason for
19
19
  we are working on.  In this case we should just return read errors from
20
20
  the file descriptior.
21
21
*/
 
22
 
22
23
#include "config.h"
23
24
#include "vio.h"
24
25
#include <string.h>
40
41
 
41
42
using namespace std;
42
43
 
43
 
Vio::Vio(int nsd)
44
 
: closed(false),
45
 
sd(nsd),
46
 
fcntl_mode(0),
47
 
read_pos(NULL),
48
 
read_end(NULL)
49
 
{
50
 
  closed= false;
51
 
  sd= nsd;
52
 
 
53
 
  /*
54
 
    We call fcntl() to set the flags and then immediately read them back
55
 
    to make sure that we and the system are in agreement on the state of
56
 
    things.
57
 
 
58
 
    An example of why we need to do this is FreeBSD (and apparently some
59
 
    other BSD-derived systems, like Mac OS X), where the system sometimes
60
 
    reports that the socket is set for non-blocking when it really will
61
 
    block.
62
 
  */
63
 
  fcntl(sd, F_SETFL, 0);
64
 
  fcntl_mode= fcntl(sd, F_GETFL);
65
 
 
66
 
  memset(&local, 0, sizeof(local));
67
 
  memset(&remote, 0, sizeof(remote));
68
 
}
69
 
 
70
 
Vio::~Vio()
71
 
{
72
 
 if (!closed)
73
 
    close();
74
 
}
75
 
 
76
 
int Vio::close()
77
 
{
78
 
  int r=0;
79
 
  if (!closed)
80
 
  {
81
 
    assert(sd >= 0);
82
 
    if (shutdown(sd, SHUT_RDWR))
83
 
      r= -1;
84
 
    if (::close(sd))
85
 
      r= -1;
86
 
  }
87
 
  closed= true;
88
 
  sd=   -1;
89
 
 
90
 
  return r;
91
 
}
92
 
 
93
 
size_t Vio::read(unsigned char* buf, size_t size)
 
44
static void _vio_delete(Vio* vio)
 
45
{
 
46
  if (!vio)
 
47
    return; /* It must be safe to delete null pointers. */
 
48
 
 
49
  if (!vio->closed)
 
50
    vio->vioclose(vio);
 
51
  free((unsigned char*) vio);
 
52
}
 
53
 
 
54
static int _vio_errno(Vio *vio)
 
55
{
 
56
  (void)vio;
 
57
  return errno;
 
58
}
 
59
 
 
60
static size_t _vio_read(Vio * vio, unsigned char* buf, size_t size)
94
61
{
95
62
  size_t r;
96
63
 
97
64
  /* Ensure nobody uses vio_read_buff and vio_read simultaneously */
98
 
  assert(read_end == read_pos);
99
 
  r= ::read(sd, buf, size);
 
65
  assert(vio->read_end == vio->read_pos);
 
66
  r= read(vio->sd, buf, size);
100
67
 
101
68
  return r;
102
69
}
103
70
 
104
 
size_t Vio::write(const unsigned char* buf, size_t size)
 
71
static size_t _vio_write(Vio * vio, const unsigned char* buf, size_t size)
105
72
{
106
73
  size_t r;
107
74
 
108
 
  r = ::write(sd, buf, size);
 
75
  r = write(vio->sd, buf, size);
109
76
 
110
77
  return r;
111
78
}
112
79
 
113
 
int Vio::blocking(bool set_blocking_mode, bool *old_mode)
 
80
static int _vio_blocking(Vio * vio, bool set_blocking_mode, bool *old_mode)
114
81
{
115
82
  int r=0;
116
83
 
117
 
  // make sure ptr is not NULL:
118
 
  if (NULL != old_mode)
119
 
    *old_mode= drizzled::test(!(fcntl_mode & O_NONBLOCK));
 
84
  *old_mode= drizzled::test(!(vio->fcntl_mode & O_NONBLOCK));
120
85
 
121
 
  if (sd >= 0)
 
86
  if (vio->sd >= 0)
122
87
  {
123
 
    int old_fcntl=fcntl_mode;
 
88
    int old_fcntl=vio->fcntl_mode;
124
89
    if (set_blocking_mode)
125
 
      fcntl_mode &= ~O_NONBLOCK; /* clear bit */
 
90
      vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
126
91
    else
127
 
      fcntl_mode |= O_NONBLOCK; /* set bit */
128
 
    if (old_fcntl != fcntl_mode)
 
92
      vio->fcntl_mode |= O_NONBLOCK; /* set bit */
 
93
    if (old_fcntl != vio->fcntl_mode)
129
94
    {
130
 
      r= fcntl(sd, F_SETFL, fcntl_mode);
 
95
      r= fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
131
96
      if (r == -1)
132
97
      {
133
 
        fcntl_mode= old_fcntl;
 
98
        vio->fcntl_mode= old_fcntl;
134
99
      }
135
100
    }
136
101
  }
138
103
  return r;
139
104
}
140
105
 
141
 
int Vio::fastsend()
 
106
static int _vio_fastsend(Vio * vio)
142
107
{
 
108
  (void)vio;
143
109
  int nodelay = 1;
144
110
  int error;
145
111
 
146
 
  error= setsockopt(sd, IPPROTO_TCP, TCP_NODELAY,
 
112
  error= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY,
147
113
                    &nodelay, sizeof(nodelay));
148
114
  if (error != 0)
149
115
  {
150
116
    perror("setsockopt");
 
117
    assert(error == 0);
151
118
  }
152
119
 
153
120
  return error;
154
121
}
155
122
 
156
 
int32_t Vio::keepalive(bool set_keep_alive)
 
123
static int32_t _vio_keepalive(Vio* vio, bool set_keep_alive)
157
124
{
158
125
  int r= 0;
159
126
  uint32_t opt= 0;
161
128
  if (set_keep_alive)
162
129
    opt= 1;
163
130
 
164
 
  r= setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
 
131
  r= setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
165
132
  if (r != 0)
166
133
  {
167
134
    perror("setsockopt");
171
138
  return r;
172
139
}
173
140
 
174
 
bool Vio::should_retry() const
 
141
static bool _vio_should_retry(Vio * vio)
175
142
{
 
143
  (void)vio;
176
144
  int en = errno;
177
145
  return (en == EAGAIN || en == EINTR ||
178
 
          en == EWOULDBLOCK);
 
146
          en == EWOULDBLOCK);
179
147
}
180
148
 
181
 
bool Vio::was_interrupted() const
 
149
static bool _vio_was_interrupted(Vio *vio)
182
150
{
 
151
  (void)vio;
183
152
  int en= errno;
184
153
  return (en == EAGAIN || en == EINTR ||
185
 
          en == EWOULDBLOCK || en == ETIMEDOUT);
186
 
}
187
 
 
188
 
bool Vio::peer_addr(char *buf, uint16_t *port, size_t buflen) const
 
154
          en == EWOULDBLOCK || en == ETIMEDOUT);
 
155
}
 
156
 
 
157
static int _vio_close(Vio * vio)
 
158
{
 
159
  int r=0;
 
160
 if (!vio->closed)
 
161
  {
 
162
    assert(vio->sd >= 0);
 
163
    if (shutdown(vio->sd, SHUT_RDWR))
 
164
      r= -1;
 
165
    if (close(vio->sd))
 
166
      r= -1;
 
167
  }
 
168
  vio->closed= true;
 
169
  vio->sd=   -1;
 
170
 
 
171
  return r;
 
172
}
 
173
 
 
174
static bool _vio_peer_addr(Vio *vio, char *buf, uint16_t *port, size_t buflen)
189
175
{
190
176
  int error;
191
177
  char port_buf[NI_MAXSERV];
192
 
  socklen_t al = sizeof(remote);
 
178
  socklen_t addrLen = sizeof(vio->remote);
193
179
 
194
 
  if (getpeername(sd, (struct sockaddr *) (&remote),
195
 
                  &al) != 0)
 
180
  if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote),
 
181
                  &addrLen) != 0)
196
182
  {
197
183
    return true;
198
184
  }
 
185
  vio->addrLen= (int)addrLen;
199
186
 
200
 
  if ((error= getnameinfo((struct sockaddr *)(&remote),
201
 
                          al,
 
187
  if ((error= getnameinfo((struct sockaddr *)(&vio->remote),
 
188
                          addrLen,
202
189
                          buf, buflen,
203
190
                          port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV)))
204
191
  {
210
197
  return false;
211
198
}
212
199
 
213
 
void Vio::timeout(bool is_sndtimeo, int32_t t)
 
200
static void _vio_timeout(Vio *vio, bool is_sndtimeo, int32_t timeout)
214
201
{
215
202
  int error;
216
203
 
217
204
  /* POSIX specifies time as struct timeval. */
218
205
  struct timeval wait_timeout;
219
 
  wait_timeout.tv_sec= t;
 
206
  wait_timeout.tv_sec= timeout;
220
207
  wait_timeout.tv_usec= 0;
221
208
 
222
 
  assert(t >= 0 && t <= INT32_MAX);
223
 
  assert(sd != -1);
224
 
  error= setsockopt(sd, SOL_SOCKET, is_sndtimeo ? SO_SNDTIMEO : SO_RCVTIMEO,
 
209
  assert(timeout >= 0 && timeout <= INT32_MAX);
 
210
  assert(vio->sd != -1);
 
211
  error= setsockopt(vio->sd, SOL_SOCKET, is_sndtimeo ? SO_SNDTIMEO : SO_RCVTIMEO,
225
212
                    &wait_timeout,
226
213
                    (socklen_t)sizeof(struct timeval));
227
214
  if (error == -1 && errno != ENOPROTOOPT)
231
218
  }
232
219
}
233
220
 
234
 
int Vio::get_errno() const
235
 
{
236
 
  return errno;
237
 
}
238
 
 
239
 
int Vio::get_fd() const
240
 
{
241
 
  return sd;
242
 
}
243
 
 
244
 
 
245
 
char *Vio::get_read_pos() const
246
 
{
247
 
  return read_pos;
248
 
}
249
 
 
250
 
char *Vio::get_read_end() const
251
 
{
252
 
  return read_end;
253
 
}
254
 
 
 
221
/* Open the socket or TCP/IP connection and read the fnctl() status */
 
222
Vio *mysql_protocol_vio_new(int sd)
 
223
{
 
224
  Vio *vio = (Vio*) malloc(sizeof(Vio));
 
225
  if (vio == NULL)
 
226
    return NULL;
 
227
 
 
228
  memset(vio, 0, sizeof(*vio));
 
229
  vio->closed= false;
 
230
  vio->sd= sd;
 
231
  vio->viodelete= _vio_delete;
 
232
  vio->vioerrno= _vio_errno;
 
233
  vio->read= _vio_read;
 
234
  vio->write= _vio_write;
 
235
  vio->fastsend= _vio_fastsend;
 
236
  vio->viokeepalive= _vio_keepalive;
 
237
  vio->should_retry= _vio_should_retry;
 
238
  vio->was_interrupted= _vio_was_interrupted;
 
239
  vio->vioclose= _vio_close;
 
240
  vio->peer_addr= _vio_peer_addr;
 
241
  vio->vioblocking= _vio_blocking;
 
242
  vio->timeout= _vio_timeout;
 
243
 
 
244
  /*
 
245
    We call fcntl() to set the flags and then immediately read them back
 
246
    to make sure that we and the system are in agreement on the state of
 
247
    things.
 
248
 
 
249
    An example of why we need to do this is FreeBSD (and apparently some
 
250
    other BSD-derived systems, like Mac OS X), where the system sometimes
 
251
    reports that the socket is set for non-blocking when it really will
 
252
    block.
 
253
  */
 
254
  fcntl(sd, F_SETFL, 0);
 
255
  vio->fcntl_mode= fcntl(sd, F_GETFL);
 
256
 
 
257
  return vio;
 
258
}