~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
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 */
15
16
/*
17
  Note that we can't have assertion on file descriptors;  The reason for
18
  this is that during mysql shutdown, another thread can close a file
19
  we are working on.  In this case we should just return read errors from
20
  the file descriptior.
21
*/
22
23
#include "vio_priv.h"
268 by Brian Aker
Merging up a bunch of assert() and cleanup of my_sock typedef
24
#include <sys/socket.h>
1 by brian
clean slate
25
26
int vio_errno(Vio *vio __attribute__((unused)))
27
{
28
  return socket_errno;		/* On Win32 this mapped to WSAGetLastError() */
29
}
30
31
32
size_t vio_read(Vio * vio, uchar* buf, size_t size)
33
{
34
  size_t r;
35
36
  /* Ensure nobody uses vio_read_buff and vio_read simultaneously */
127 by brian
Removed DBUG statements from VIO
37
  assert(vio->read_end == vio->read_pos);
172 by Brian Aker
First pass of cleanup
38
  r= read(vio->sd, buf, size);
39
127 by brian
Removed DBUG statements from VIO
40
  return r;
1 by brian
clean slate
41
}
42
43
44
/*
45
  Buffered read: if average read size is small it may
46
  reduce number of syscalls.
47
*/
48
49
size_t vio_read_buff(Vio *vio, uchar* buf, size_t size)
50
{
51
  size_t rc;
52
#define VIO_UNBUFFERED_READ_MIN_SIZE 2048
53
54
  if (vio->read_pos < vio->read_end)
55
  {
56
    rc= min((size_t) (vio->read_end - vio->read_pos), size);
57
    memcpy(buf, vio->read_pos, rc);
58
    vio->read_pos+= rc;
59
    /*
60
      Do not try to read from the socket now even if rc < size:
61
      vio_read can return -1 due to an error or non-blocking mode, and
62
      the safest way to handle it is to move to a separate branch.
63
    */
64
  }
65
  else if (size < VIO_UNBUFFERED_READ_MIN_SIZE)
66
  {
67
    rc= vio_read(vio, (uchar*) vio->read_buffer, VIO_READ_BUFFER_SIZE);
68
    if (rc != 0 && rc != (size_t) -1)
69
    {
70
      if (rc > size)
71
      {
72
        vio->read_pos= vio->read_buffer + size;
73
        vio->read_end= vio->read_buffer + rc;
74
        rc= size;
75
      }
76
      memcpy(buf, vio->read_buffer, rc);
77
    }
78
  }
79
  else
80
    rc= vio_read(vio, buf, size);
127 by brian
Removed DBUG statements from VIO
81
82
  return rc;
1 by brian
clean slate
83
#undef VIO_UNBUFFERED_READ_MIN_SIZE
84
}
85
86
87
size_t vio_write(Vio * vio, const uchar* buf, size_t size)
88
{
89
  size_t r;
127 by brian
Removed DBUG statements from VIO
90
1 by brian
clean slate
91
  r = write(vio->sd, buf, size);
127 by brian
Removed DBUG statements from VIO
92
93
  return r;
1 by brian
clean slate
94
}
95
173 by Brian Aker
Removed thd alarm around socket, we now use timeouts.
96
int vio_blocking(Vio * vio, bool set_blocking_mode, bool *old_mode)
1 by brian
clean slate
97
{
98
  int r=0;
99
100
  *old_mode= test(!(vio->fcntl_mode & O_NONBLOCK));
101
102
  if (vio->sd >= 0)
103
  {
104
    int old_fcntl=vio->fcntl_mode;
105
    if (set_blocking_mode)
106
      vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
107
    else
108
      vio->fcntl_mode |= O_NONBLOCK; /* set bit */
109
    if (old_fcntl != vio->fcntl_mode)
110
    {
111
      r= fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
112
      if (r == -1)
113
      {
114
        vio->fcntl_mode= old_fcntl;
115
      }
116
    }
117
  }
172 by Brian Aker
First pass of cleanup
118
127 by brian
Removed DBUG statements from VIO
119
  return r;
1 by brian
clean slate
120
}
121
172 by Brian Aker
First pass of cleanup
122
bool
1 by brian
clean slate
123
vio_is_blocking(Vio * vio)
124
{
172 by Brian Aker
First pass of cleanup
125
  bool r;
1 by brian
clean slate
126
  r = !(vio->fcntl_mode & O_NONBLOCK);
127 by brian
Removed DBUG statements from VIO
127
128
  return r;
1 by brian
clean slate
129
}
130
131
132
int vio_fastsend(Vio * vio __attribute__((unused)))
133
{
172 by Brian Aker
First pass of cleanup
134
  int nodelay = 1;
267 by Brian Aker
More error control around socket calls.
135
  int error;
136
137
  error= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY,
138
                    &nodelay, sizeof(nodelay));
139
  if (error != 0)
140
  {
141
    perror("setsockopt");
142
    assert(error == 0);
143
  }
144
145
  return error;
1 by brian
clean slate
146
}
147
172 by Brian Aker
First pass of cleanup
148
int32_t vio_keepalive(Vio* vio, bool set_keep_alive)
1 by brian
clean slate
149
{
127 by brian
Removed DBUG statements from VIO
150
  int r= 0;
172 by Brian Aker
First pass of cleanup
151
  uint32_t opt= 0;
152
153
  if (set_keep_alive)
154
    opt= 1;
155
156
  r= setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
267 by Brian Aker
More error control around socket calls.
157
  if (r != 0)
158
  {
159
    perror("setsockopt");
160
    assert(r == 0);
161
  }
127 by brian
Removed DBUG statements from VIO
162
163
  return r;
1 by brian
clean slate
164
}
165
166
172 by Brian Aker
First pass of cleanup
167
bool
1 by brian
clean slate
168
vio_should_retry(Vio * vio __attribute__((unused)))
169
{
170
  int en = socket_errno;
171
  return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
172
	  en == SOCKET_EWOULDBLOCK);
173
}
174
175
172 by Brian Aker
First pass of cleanup
176
bool
1 by brian
clean slate
177
vio_was_interrupted(Vio *vio __attribute__((unused)))
178
{
179
  int en= socket_errno;
180
  return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
181
	  en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT);
182
}
183
184
185
int vio_close(Vio * vio)
186
{
187
  int r=0;
188
 if (vio->type != VIO_CLOSED)
189
  {
127 by brian
Removed DBUG statements from VIO
190
    assert(vio->sd >= 0);
1 by brian
clean slate
191
    if (shutdown(vio->sd, SHUT_RDWR))
192
      r= -1;
293 by Brian Aker
Merge + closesocket() fix
193
    if (close(vio->sd))
1 by brian
clean slate
194
      r= -1;
195
  }
196
  vio->type= VIO_CLOSED;
197
  vio->sd=   -1;
127 by brian
Removed DBUG statements from VIO
198
199
  return r;
1 by brian
clean slate
200
}
201
202
203
const char *vio_description(Vio * vio)
204
{
205
  return vio->desc;
206
}
207
208
enum enum_vio_type vio_type(Vio* vio)
209
{
210
  return vio->type;
211
}
212
268 by Brian Aker
Merging up a bunch of assert() and cleanup of my_sock typedef
213
int vio_fd(Vio* vio)
1 by brian
clean slate
214
{
215
  return vio->sd;
216
}
217
172 by Brian Aker
First pass of cleanup
218
bool vio_peer_addr(Vio *vio, char *buf, uint16_t *port, size_t buflen)
1 by brian
clean slate
219
{
172 by Brian Aker
First pass of cleanup
220
  int error;
221
  char port_buf[NI_MAXSERV];
212.5.29 by Monty Taylor
Changed to work around ubuntu 32-bit.
222
  socklen_t addrLen = sizeof(vio->remote);
172 by Brian Aker
First pass of cleanup
223
224
  if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote),
225
                  &addrLen) != 0)
226
  {
227
    return true;
228
  }
229
  vio->addrLen= (int)addrLen;
230
231
  if ((error= getnameinfo((struct sockaddr *)(&vio->remote), 
232
                          addrLen,
233
                          buf, buflen,
234
                          port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV)))
235
  {
236
    return true;
237
  }
238
239
  *port= (uint16_t)strtol(port_buf, (char **)NULL, 10);
127 by brian
Removed DBUG statements from VIO
240
241
  return false;
1 by brian
clean slate
242
}
243
244
245
/* Return 0 if there is data to be read */
246
268 by Brian Aker
Merging up a bunch of assert() and cleanup of my_sock typedef
247
bool vio_poll_read(Vio *vio, int32_t timeout)
1 by brian
clean slate
248
{
249
  struct pollfd fds;
250
  int res;
127 by brian
Removed DBUG statements from VIO
251
1 by brian
clean slate
252
  fds.fd=vio->sd;
253
  fds.events=POLLIN;
254
  fds.revents=0;
255
  if ((res=poll(&fds,1,(int) timeout*1000)) <= 0)
256
  {
127 by brian
Removed DBUG statements from VIO
257
    return res < 0 ? false : true;		/* Don't return 1 on errors */
1 by brian
clean slate
258
  }
127 by brian
Removed DBUG statements from VIO
259
  return (fds.revents & (POLLIN | POLLERR | POLLHUP) ? false : true);
1 by brian
clean slate
260
}
261
262
172 by Brian Aker
First pass of cleanup
263
bool vio_peek_read(Vio *vio, uint32_t *bytes)
1 by brian
clean slate
264
{
265
  char buf[1024];
266
  ssize_t res= recv(vio->sd, &buf, sizeof(buf), MSG_PEEK);
172 by Brian Aker
First pass of cleanup
267
1 by brian
clean slate
268
  if (res < 0)
163 by Brian Aker
Merge Monty's code.
269
    return true;
172 by Brian Aker
First pass of cleanup
270
  *bytes= (uint32_t)res;
163 by Brian Aker
Merge Monty's code.
271
  return false;
1 by brian
clean slate
272
}
273
268 by Brian Aker
Merging up a bunch of assert() and cleanup of my_sock typedef
274
void vio_timeout(Vio *vio, bool is_sndtimeo, int32_t timeout)
1 by brian
clean slate
275
{
268 by Brian Aker
Merging up a bunch of assert() and cleanup of my_sock typedef
276
  int error;
1 by brian
clean slate
277
278
  /* POSIX specifies time as struct timeval. */
279
  struct timeval wait_timeout;
280
  wait_timeout.tv_sec= timeout;
281
  wait_timeout.tv_usec= 0;
282
268 by Brian Aker
Merging up a bunch of assert() and cleanup of my_sock typedef
283
  assert(timeout >= 0 && timeout <= INT32_MAX);
284
  assert(vio->sd != -1);
285
  error= setsockopt(vio->sd, SOL_SOCKET, is_sndtimeo ? SO_SNDTIMEO : SO_RCVTIMEO,
286
                    &wait_timeout,
287
                    (socklen_t)sizeof(struct timeval));
288
  if (error != 0)
267 by Brian Aker
More error control around socket calls.
289
  {
290
    perror("setsockopt");
268 by Brian Aker
Merging up a bunch of assert() and cleanup of my_sock typedef
291
    assert(error == 0);
267 by Brian Aker
More error control around socket calls.
292
  }
1 by brian
clean slate
293
}