~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/mysql_protocol/vio.cc

  • Committer: Andrew Hutchings
  • Date: 2011-01-21 11:23:19 UTC
  • mto: (2100.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 2101.
  • Revision ID: andrew@linuxjedi.co.uk-20110121112319-nj1cvg0yt3nnf2rr
Add errors page to drizzle client docs
Add link to specific error in migration docs
Minor changes to migration docs

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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  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
 
 
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
namespace drizzle_plugin
 
44
{
 
45
 
 
46
Vio::Vio(int nsd) :
 
47
  closed(false),
 
48
  sd(nsd),
 
49
  fcntl_mode(0),
 
50
  local(),
 
51
  remote(),
 
52
  read_pos(NULL),
 
53
  read_end(NULL)
 
54
{
 
55
  /*
 
56
    We call fcntl() to set the flags and then immediately read them back
 
57
    to make sure that we and the system are in agreement on the state of
 
58
    things.
 
59
 
 
60
    An example of why we need to do this is FreeBSD (and apparently some
 
61
    other BSD-derived systems, like Mac OS X), where the system sometimes
 
62
    reports that the socket is set for non-blocking when it really will
 
63
    block.
 
64
  */
 
65
  fcntl(sd, F_SETFL, 0);
 
66
  fcntl_mode= fcntl(sd, F_GETFL);
 
67
}
 
68
 
 
69
Vio::~Vio()
 
70
{
 
71
 if (!closed)
 
72
    close();
 
73
}
 
74
 
 
75
int Vio::close()
 
76
{
 
77
  int r=0;
 
78
  if (!closed)
 
79
  {
 
80
    assert(sd >= 0);
 
81
    if (shutdown(sd, SHUT_RDWR))
 
82
      r= -1;
 
83
    if (::close(sd))
 
84
      r= -1;
 
85
  }
 
86
  closed= true;
 
87
  sd=   -1;
 
88
 
 
89
  return r;
 
90
}
 
91
 
 
92
size_t Vio::read(unsigned char* buf, size_t size)
61
93
{
62
94
  size_t r;
63
95
 
64
96
  /* 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);
 
97
  assert(read_end == read_pos);
 
98
  r= ::read(sd, buf, size);
67
99
 
68
100
  return r;
69
101
}
70
102
 
71
 
static size_t _vio_write(Vio * vio, const unsigned char* buf, size_t size)
 
103
size_t Vio::write(const unsigned char* buf, size_t size)
72
104
{
73
105
  size_t r;
74
106
 
75
 
  r = write(vio->sd, buf, size);
 
107
  r = ::write(sd, buf, size);
76
108
 
77
109
  return r;
78
110
}
79
111
 
80
 
static int _vio_blocking(Vio * vio, bool set_blocking_mode, bool *old_mode)
 
112
int Vio::blocking(bool set_blocking_mode, bool *old_mode)
81
113
{
82
114
  int r=0;
83
115
 
84
 
  *old_mode= drizzled::test(!(vio->fcntl_mode & O_NONBLOCK));
 
116
  // make sure ptr is not NULL:
 
117
  if (NULL != old_mode)
 
118
    *old_mode= drizzled::test(!(fcntl_mode & O_NONBLOCK));
85
119
 
86
 
  if (vio->sd >= 0)
 
120
  if (sd >= 0)
87
121
  {
88
 
    int old_fcntl=vio->fcntl_mode;
 
122
    int old_fcntl=fcntl_mode;
89
123
    if (set_blocking_mode)
90
 
      vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
 
124
      fcntl_mode &= ~O_NONBLOCK; /* clear bit */
91
125
    else
92
 
      vio->fcntl_mode |= O_NONBLOCK; /* set bit */
93
 
    if (old_fcntl != vio->fcntl_mode)
 
126
      fcntl_mode |= O_NONBLOCK; /* set bit */
 
127
    if (old_fcntl != fcntl_mode)
94
128
    {
95
 
      r= fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
 
129
      r= fcntl(sd, F_SETFL, fcntl_mode);
96
130
      if (r == -1)
97
131
      {
98
 
        vio->fcntl_mode= old_fcntl;
 
132
        fcntl_mode= old_fcntl;
99
133
      }
100
134
    }
101
135
  }
103
137
  return r;
104
138
}
105
139
 
106
 
static int _vio_fastsend(Vio * vio)
 
140
int Vio::fastsend()
107
141
{
108
 
  (void)vio;
109
142
  int nodelay = 1;
110
143
  int error;
111
144
 
112
 
  error= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY,
 
145
  error= setsockopt(sd, IPPROTO_TCP, TCP_NODELAY,
113
146
                    &nodelay, sizeof(nodelay));
114
147
  if (error != 0)
115
148
  {
116
149
    perror("setsockopt");
117
 
    assert(error == 0);
118
150
  }
119
151
 
120
152
  return error;
121
153
}
122
154
 
123
 
static int32_t _vio_keepalive(Vio* vio, bool set_keep_alive)
 
155
int32_t Vio::keepalive(bool set_keep_alive)
124
156
{
125
157
  int r= 0;
126
158
  uint32_t opt= 0;
128
160
  if (set_keep_alive)
129
161
    opt= 1;
130
162
 
131
 
  r= setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
 
163
  r= setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
132
164
  if (r != 0)
133
165
  {
134
166
    perror("setsockopt");
138
170
  return r;
139
171
}
140
172
 
141
 
static bool _vio_should_retry(Vio * vio)
 
173
bool Vio::should_retry() const
142
174
{
143
 
  (void)vio;
144
175
  int en = errno;
145
176
  return (en == EAGAIN || en == EINTR ||
146
 
          en == EWOULDBLOCK);
 
177
          en == EWOULDBLOCK);
147
178
}
148
179
 
149
 
static bool _vio_was_interrupted(Vio *vio)
 
180
bool Vio::was_interrupted() const
150
181
{
151
 
  (void)vio;
152
182
  int en= errno;
153
183
  return (en == EAGAIN || en == EINTR ||
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)
 
184
          en == EWOULDBLOCK || en == ETIMEDOUT);
 
185
}
 
186
 
 
187
bool Vio::peer_addr(char *buf, uint16_t *port, size_t buflen) const
175
188
{
176
189
  int error;
177
190
  char port_buf[NI_MAXSERV];
178
 
  socklen_t addrLen = sizeof(vio->remote);
 
191
  socklen_t al = sizeof(remote);
179
192
 
180
 
  if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote),
181
 
                  &addrLen) != 0)
 
193
  if (getpeername(sd, (struct sockaddr *) (&remote),
 
194
                  &al) != 0)
182
195
  {
183
196
    return true;
184
197
  }
185
 
  vio->addrLen= (int)addrLen;
186
198
 
187
 
  if ((error= getnameinfo((struct sockaddr *)(&vio->remote),
188
 
                          addrLen,
 
199
  if ((error= getnameinfo((struct sockaddr *)(&remote),
 
200
                          al,
189
201
                          buf, buflen,
190
202
                          port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV)))
191
203
  {
197
209
  return false;
198
210
}
199
211
 
200
 
static void _vio_timeout(Vio *vio, bool is_sndtimeo, int32_t timeout)
 
212
void Vio::timeout(bool is_sndtimeo, int32_t t)
201
213
{
202
214
  int error;
203
215
 
204
216
  /* POSIX specifies time as struct timeval. */
205
217
  struct timeval wait_timeout;
206
 
  wait_timeout.tv_sec= timeout;
 
218
  wait_timeout.tv_sec= t;
207
219
  wait_timeout.tv_usec= 0;
208
220
 
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,
 
221
  assert(t >= 0 && t <= INT32_MAX);
 
222
  assert(sd != -1);
 
223
  error= setsockopt(sd, SOL_SOCKET, is_sndtimeo ? SO_SNDTIMEO : SO_RCVTIMEO,
212
224
                    &wait_timeout,
213
225
                    (socklen_t)sizeof(struct timeval));
214
226
  if (error == -1 && errno != ENOPROTOOPT)
218
230
  }
219
231
}
220
232
 
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
 
}
 
233
int Vio::get_errno() const
 
234
{
 
235
  return errno;
 
236
}
 
237
 
 
238
int Vio::get_fd() const
 
239
{
 
240
  return sd;
 
241
}
 
242
 
 
243
 
 
244
char *Vio::get_read_pos() const
 
245
{
 
246
  return read_pos;
 
247
}
 
248
 
 
249
char *Vio::get_read_end() const
 
250
{
 
251
  return read_end;
 
252
}
 
253
 
 
254
} /* namespace drizzle_plugin */