~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/mysql_protocol/vio.cc

Merge Thomi - Changed the vio_st structure (found in plugins/mysql_protocol/vio.h) to a proper C++ class.

Show diffs side-by-side

added added

removed removed

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