~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to vio/viosocket.c

  • Committer: Brian Aker
  • Date: 2008-07-01 07:17:30 UTC
  • Revision ID: brian@tangent.org-20080701071730-y843dzfwz1nbca79
More mysys removal

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
  the file descriptior.
21
21
*/
22
22
 
23
 
#define DONT_MAP_VIO
24
 
#include <drizzled/global.h>
25
 
#include "vio.h"
26
 
#include <drizzled/util/test.h>
27
 
 
28
 
#include <sys/socket.h>
29
 
#include <string.h>
30
 
 
31
 
#include <netinet/tcp.h>
32
 
#include <sys/poll.h>
33
 
 
34
 
#include <netdb.h>
35
 
 
36
 
#include <algorithm>
37
 
 
38
 
using namespace std;
39
 
 
40
 
int drizzleclient_vio_errno(Vio *vio)
 
23
#include "vio_priv.h"
 
24
 
 
25
int vio_errno(Vio *vio __attribute__((unused)))
41
26
{
42
 
  (void)vio;
43
 
  return errno;
 
27
  return socket_errno;          /* On Win32 this mapped to WSAGetLastError() */
44
28
}
45
29
 
46
30
 
47
 
size_t drizzleclient_vio_read(Vio * vio, unsigned char* buf, size_t size)
 
31
size_t vio_read(Vio * vio, uchar* buf, size_t size)
48
32
{
49
33
  size_t r;
50
 
 
51
 
  /* Ensure nobody uses drizzleclient_vio_read_buff and drizzleclient_vio_read simultaneously */
52
 
  assert(vio->read_end == vio->read_pos);
53
 
  r= read(vio->sd, buf, size);
54
 
 
55
 
  return r;
 
34
  DBUG_ENTER("vio_read");
 
35
  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u", vio->sd, (long) buf,
 
36
                       (uint) size));
 
37
 
 
38
  /* Ensure nobody uses vio_read_buff and vio_read simultaneously */
 
39
  DBUG_ASSERT(vio->read_end == vio->read_pos);
 
40
#ifdef __WIN__
 
41
  r = recv(vio->sd, buf, size,0);
 
42
#else
 
43
  errno=0;                                      /* For linux */
 
44
  r = read(vio->sd, buf, size);
 
45
#endif /* __WIN__ */
 
46
#ifndef DBUG_OFF
 
47
  if (r == (size_t) -1)
 
48
  {
 
49
    DBUG_PRINT("vio_error", ("Got error %d during read",errno));
 
50
  }
 
51
#endif /* DBUG_OFF */
 
52
  DBUG_PRINT("exit", ("%ld", (long) r));
 
53
  DBUG_RETURN(r);
56
54
}
57
55
 
58
56
 
61
59
  reduce number of syscalls.
62
60
*/
63
61
 
64
 
size_t drizzleclient_vio_read_buff(Vio *vio, unsigned char* buf, size_t size)
 
62
size_t vio_read_buff(Vio *vio, uchar* buf, size_t size)
65
63
{
66
64
  size_t rc;
67
65
#define VIO_UNBUFFERED_READ_MIN_SIZE 2048
 
66
  DBUG_ENTER("vio_read_buff");
 
67
  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u", vio->sd, (long) buf,
 
68
                       (uint) size));
68
69
 
69
70
  if (vio->read_pos < vio->read_end)
70
71
  {
73
74
    vio->read_pos+= rc;
74
75
    /*
75
76
      Do not try to read from the socket now even if rc < size:
76
 
      drizzleclient_vio_read can return -1 due to an error or non-blocking mode, and
 
77
      vio_read can return -1 due to an error or non-blocking mode, and
77
78
      the safest way to handle it is to move to a separate branch.
78
79
    */
79
80
  }
80
81
  else if (size < VIO_UNBUFFERED_READ_MIN_SIZE)
81
82
  {
82
 
    rc= drizzleclient_vio_read(vio, (unsigned char*) vio->read_buffer, VIO_READ_BUFFER_SIZE);
 
83
    rc= vio_read(vio, (uchar*) vio->read_buffer, VIO_READ_BUFFER_SIZE);
83
84
    if (rc != 0 && rc != (size_t) -1)
84
85
    {
85
86
      if (rc > size)
92
93
    }
93
94
  }
94
95
  else
95
 
    rc= drizzleclient_vio_read(vio, buf, size);
96
 
 
97
 
  return rc;
 
96
    rc= vio_read(vio, buf, size);
 
97
  DBUG_RETURN(rc);
98
98
#undef VIO_UNBUFFERED_READ_MIN_SIZE
99
99
}
100
100
 
101
101
 
102
 
size_t drizzleclient_vio_write(Vio * vio, const unsigned char* buf, size_t size)
 
102
size_t vio_write(Vio * vio, const uchar* buf, size_t size)
103
103
{
104
104
  size_t r;
105
 
 
 
105
  DBUG_ENTER("vio_write");
 
106
  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u", vio->sd, (long) buf,
 
107
                       (uint) size));
 
108
#ifdef __WIN__
 
109
  r = send(vio->sd, buf, size,0);
 
110
#else
106
111
  r = write(vio->sd, buf, size);
107
 
 
108
 
  return r;
 
112
#endif /* __WIN__ */
 
113
#ifndef DBUG_OFF
 
114
  if (r == (size_t) -1)
 
115
  {
 
116
    DBUG_PRINT("vio_error", ("Got error on write: %d",socket_errno));
 
117
  }
 
118
#endif /* DBUG_OFF */
 
119
  DBUG_PRINT("exit", ("%u", (uint) r));
 
120
  DBUG_RETURN(r);
109
121
}
110
122
 
111
 
int drizzleclient_vio_blocking(Vio * vio, bool set_blocking_mode, bool *old_mode)
 
123
int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode,
 
124
                 my_bool *old_mode)
112
125
{
113
126
  int r=0;
 
127
  DBUG_ENTER("vio_blocking");
114
128
 
115
129
  *old_mode= test(!(vio->fcntl_mode & O_NONBLOCK));
 
130
  DBUG_PRINT("enter", ("set_blocking_mode: %d  old_mode: %d",
 
131
                       (int) set_blocking_mode, (int) *old_mode));
116
132
 
 
133
#if !defined(__WIN__)
 
134
#if !defined(NO_FCNTL_NONBLOCK)
117
135
  if (vio->sd >= 0)
118
136
  {
119
137
    int old_fcntl=vio->fcntl_mode;
126
144
      r= fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
127
145
      if (r == -1)
128
146
      {
 
147
        DBUG_PRINT("info", ("fcntl failed, errno %d", errno));
129
148
        vio->fcntl_mode= old_fcntl;
130
149
      }
131
150
    }
132
151
  }
133
 
 
134
 
  return r;
 
152
#else
 
153
  r= set_blocking_mode ? 0 : 1;
 
154
#endif /* !defined(NO_FCNTL_NONBLOCK) */
 
155
#else /* !defined(__WIN__) */
 
156
  if (vio->type != VIO_TYPE_NAMEDPIPE && vio->type != VIO_TYPE_SHARED_MEMORY)
 
157
  { 
 
158
    ulong arg;
 
159
    int old_fcntl=vio->fcntl_mode;
 
160
    if (set_blocking_mode)
 
161
    {
 
162
      arg = 0;
 
163
      vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
 
164
    }
 
165
    else
 
166
    {
 
167
      arg = 1;
 
168
      vio->fcntl_mode |= O_NONBLOCK; /* set bit */
 
169
    }
 
170
    if (old_fcntl != vio->fcntl_mode)
 
171
      r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg);
 
172
  }
 
173
  else
 
174
    r=  test(!(vio->fcntl_mode & O_NONBLOCK)) != set_blocking_mode;
 
175
#endif /* !defined(__WIN__) */
 
176
  DBUG_PRINT("exit", ("%d", r));
 
177
  DBUG_RETURN(r);
135
178
}
136
179
 
137
 
bool
138
 
drizzleclient_vio_is_blocking(Vio * vio)
 
180
my_bool
 
181
vio_is_blocking(Vio * vio)
139
182
{
140
 
  bool r;
 
183
  my_bool r;
 
184
  DBUG_ENTER("vio_is_blocking");
141
185
  r = !(vio->fcntl_mode & O_NONBLOCK);
142
 
 
143
 
  return r;
144
 
}
145
 
 
146
 
 
147
 
int drizzleclient_vio_fastsend(Vio * vio)
148
 
{
149
 
  (void)vio;
150
 
  int nodelay = 1;
151
 
  int error;
152
 
 
153
 
  error= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY,
154
 
                    &nodelay, sizeof(nodelay));
155
 
  if (error != 0)
156
 
  {
157
 
    perror("setsockopt");
158
 
    assert(error == 0);
159
 
  }
160
 
 
161
 
  return error;
162
 
}
163
 
 
164
 
int32_t drizzleclient_vio_keepalive(Vio* vio, bool set_keep_alive)
165
 
{
166
 
  int r= 0;
167
 
  uint32_t opt= 0;
168
 
 
169
 
  if (set_keep_alive)
170
 
    opt= 1;
171
 
 
172
 
  r= setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
173
 
  if (r != 0)
174
 
  {
175
 
    perror("setsockopt");
176
 
    assert(r == 0);
177
 
  }
178
 
 
179
 
  return r;
180
 
}
181
 
 
182
 
 
183
 
bool
184
 
drizzleclient_vio_should_retry(Vio * vio)
185
 
{
186
 
  (void)vio;
187
 
  int en = errno;
188
 
  return (en == EAGAIN || en == EINTR ||
189
 
          en == EWOULDBLOCK);
190
 
}
191
 
 
192
 
 
193
 
bool
194
 
drizzleclient_vio_was_interrupted(Vio *vio)
195
 
{
196
 
  (void)vio;
197
 
  int en= errno;
198
 
  return (en == EAGAIN || en == EINTR ||
199
 
          en == EWOULDBLOCK || en == ETIMEDOUT);
200
 
}
201
 
 
202
 
 
203
 
int drizzleclient_vio_close(Vio * vio)
204
 
{
205
 
  int r=0;
 
186
  DBUG_PRINT("exit", ("%d", (int) r));
 
187
  DBUG_RETURN(r);
 
188
}
 
189
 
 
190
 
 
191
int vio_fastsend(Vio * vio __attribute__((unused)))
 
192
{
 
193
  int r=0;
 
194
  DBUG_ENTER("vio_fastsend");
 
195
 
 
196
#if defined(IPTOS_THROUGHPUT)
 
197
  {
 
198
    int tos = IPTOS_THROUGHPUT;
 
199
    r= setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos));
 
200
  }
 
201
#endif                                    /* IPTOS_THROUGHPUT */
 
202
  if (!r)
 
203
  {
 
204
#ifdef __WIN__
 
205
    BOOL nodelay= 1;
 
206
#else
 
207
    int nodelay = 1;
 
208
#endif
 
209
 
 
210
    r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY,
 
211
                  IF_WIN(const char*, void*) &nodelay,
 
212
                  sizeof(nodelay));
 
213
 
 
214
  }
 
215
  if (r)
 
216
  {
 
217
    DBUG_PRINT("warning", ("Couldn't set socket option for fast send"));
 
218
    r= -1;
 
219
  }
 
220
  DBUG_PRINT("exit", ("%d", r));
 
221
  DBUG_RETURN(r);
 
222
}
 
223
 
 
224
int vio_keepalive(Vio* vio, my_bool set_keep_alive)
 
225
{
 
226
  int r=0;
 
227
  uint opt = 0;
 
228
  DBUG_ENTER("vio_keepalive");
 
229
  DBUG_PRINT("enter", ("sd: %d  set_keep_alive: %d", vio->sd, (int)
 
230
                       set_keep_alive));
 
231
  if (vio->type != VIO_TYPE_NAMEDPIPE)
 
232
  {
 
233
    if (set_keep_alive)
 
234
      opt = 1;
 
235
    r = setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
 
236
                   sizeof(opt));
 
237
  }
 
238
  DBUG_RETURN(r);
 
239
}
 
240
 
 
241
 
 
242
my_bool
 
243
vio_should_retry(Vio * vio __attribute__((unused)))
 
244
{
 
245
  int en = socket_errno;
 
246
  return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
 
247
          en == SOCKET_EWOULDBLOCK);
 
248
}
 
249
 
 
250
 
 
251
my_bool
 
252
vio_was_interrupted(Vio *vio __attribute__((unused)))
 
253
{
 
254
  int en= socket_errno;
 
255
  return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
 
256
          en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT);
 
257
}
 
258
 
 
259
 
 
260
int vio_close(Vio * vio)
 
261
{
 
262
  int r=0;
 
263
  DBUG_ENTER("vio_close");
 
264
#ifdef __WIN__
 
265
  if (vio->type == VIO_TYPE_NAMEDPIPE)
 
266
  {
 
267
#if defined(__NT__) && defined(MYSQL_SERVER)
 
268
    CancelIo(vio->hPipe);
 
269
    DisconnectNamedPipe(vio->hPipe);
 
270
#endif
 
271
    r=CloseHandle(vio->hPipe);
 
272
  }
 
273
  else
 
274
#endif /* __WIN__ */
206
275
 if (vio->type != VIO_CLOSED)
207
276
  {
208
 
    assert(vio->sd >= 0);
 
277
    DBUG_ASSERT(vio->sd >= 0);
209
278
    if (shutdown(vio->sd, SHUT_RDWR))
210
279
      r= -1;
211
 
    if (close(vio->sd))
 
280
    if (closesocket(vio->sd))
212
281
      r= -1;
213
282
  }
 
283
  if (r)
 
284
  {
 
285
    DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno));
 
286
    /* FIXME: error handling (not critical for MySQL) */
 
287
  }
214
288
  vio->type= VIO_CLOSED;
215
289
  vio->sd=   -1;
216
 
 
217
 
  return r;
 
290
  DBUG_RETURN(r);
218
291
}
219
292
 
220
293
 
221
 
const char *drizzleclient_vio_description(Vio * vio)
 
294
const char *vio_description(Vio * vio)
222
295
{
223
296
  return vio->desc;
224
297
}
225
298
 
226
 
enum enum_vio_type drizzleclient_vio_type(Vio* vio)
 
299
enum enum_vio_type vio_type(Vio* vio)
227
300
{
228
301
  return vio->type;
229
302
}
230
303
 
231
 
int drizzleclient_vio_fd(Vio* vio)
 
304
my_socket vio_fd(Vio* vio)
232
305
{
233
306
  return vio->sd;
234
307
}
235
308
 
236
 
bool drizzleclient_vio_peer_addr(Vio *vio, char *buf, uint16_t *port, size_t buflen)
 
309
my_bool vio_peer_addr(Vio *vio, char *buf, uint16 *port, size_t buflen)
237
310
{
238
 
  int error;
239
 
  char port_buf[NI_MAXSERV];
240
 
  socklen_t addrLen = sizeof(vio->remote);
241
 
 
242
 
  if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote),
243
 
                  &addrLen) != 0)
244
 
  {
245
 
    return true;
246
 
  }
247
 
  vio->addrLen= (int)addrLen;
248
 
 
249
 
  if ((error= getnameinfo((struct sockaddr *)(&vio->remote),
250
 
                          addrLen,
251
 
                          buf, buflen,
252
 
                          port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV)))
253
 
  {
254
 
    return true;
255
 
  }
256
 
 
257
 
  *port= (uint16_t)strtol(port_buf, (char **)NULL, 10);
258
 
 
259
 
  return false;
 
311
  DBUG_ENTER("vio_peer_addr");
 
312
  DBUG_PRINT("enter", ("sd: %d", vio->sd));
 
313
 
 
314
  if (vio->localhost)
 
315
  {
 
316
    strmov(buf, "127.0.0.1");
 
317
    *port= 0;
 
318
  }
 
319
  else
 
320
  {
 
321
    int error;
 
322
    char port_buf[NI_MAXSERV];
 
323
    size_socket addrLen = sizeof(vio->remote);
 
324
    if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote),
 
325
                    &addrLen) != 0)
 
326
    {
 
327
      DBUG_PRINT("exit", ("getpeername gave error: %d", socket_errno));
 
328
      DBUG_RETURN(1);
 
329
    }
 
330
    vio->addrLen= (int)addrLen;
 
331
 
 
332
    if ((error= getnameinfo((struct sockaddr *)(&vio->remote), 
 
333
                            addrLen,
 
334
                            buf, buflen,
 
335
                            port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV)))
 
336
    {
 
337
      DBUG_PRINT("exit", ("getnameinfo gave error: %s", 
 
338
                          gai_strerror(error)));
 
339
      DBUG_RETURN(1);
 
340
    }
 
341
 
 
342
    *port= (uint16)strtol(port_buf, (char **)NULL, 10);
 
343
 
 
344
    /*
 
345
      A lot of users do not have IPv6 loopback resolving to localhost
 
346
      correctly setup. Should this exist? No. If we do not do it though
 
347
      we will be getting a lot of support questions from users who
 
348
      have bad setups. This code should be removed by say... 2012.
 
349
        -Brian
 
350
    */
 
351
    if (!memcmp(buf, "::ffff:127.0.0.1", sizeof("::ffff:127.0.0.1")))
 
352
      strmov(buf, "127.0.0.1");
 
353
  }
 
354
  DBUG_PRINT("exit", ("addr: %s", buf));
 
355
  DBUG_RETURN(0);
260
356
}
261
357
 
262
358
 
263
359
/* Return 0 if there is data to be read */
264
360
 
265
 
bool drizzleclient_vio_poll_read(Vio *vio, int32_t timeout)
 
361
my_bool vio_poll_read(Vio *vio,uint timeout)
266
362
{
 
363
#ifdef __WIN__
 
364
  int res;
 
365
  my_socket fd= vio->sd;
 
366
  fd_set readfds, errorfds;
 
367
  struct timeval tm;
 
368
  DBUG_ENTER("vio_poll");
 
369
  tm.tv_sec= timeout;
 
370
  tm.tv_usec= 0;
 
371
  FD_ZERO(&readfds);
 
372
  FD_ZERO(&errorfds);
 
373
  FD_SET(fd, &readfds);
 
374
  FD_SET(fd, &errorfds);
 
375
  /* The first argument is ignored on Windows, so a conversion to int is OK */
 
376
  if ((res= select((int) fd, &readfds, NULL, &errorfds, &tm) <= 0))
 
377
  {
 
378
    DBUG_RETURN(res < 0 ? 0 : 1);
 
379
  }
 
380
  res= FD_ISSET(fd, &readfds) || FD_ISSET(fd, &errorfds);
 
381
  DBUG_RETURN(!res);
 
382
#elif defined(HAVE_POLL)
267
383
  struct pollfd fds;
268
384
  int res;
269
 
 
 
385
  DBUG_ENTER("vio_poll");
270
386
  fds.fd=vio->sd;
271
387
  fds.events=POLLIN;
272
388
  fds.revents=0;
273
389
  if ((res=poll(&fds,1,(int) timeout*1000)) <= 0)
274
390
  {
275
 
    return res < 0 ? false : true;              /* Don't return 1 on errors */
 
391
    DBUG_RETURN(res < 0 ? 0 : 1);               /* Don't return 1 on errors */
276
392
  }
277
 
  return (fds.revents & (POLLIN | POLLERR | POLLHUP) ? false : true);
 
393
  DBUG_RETURN(fds.revents & (POLLIN | POLLERR | POLLHUP) ? 0 : 1);
 
394
#else
 
395
  return 0;
 
396
#endif
278
397
}
279
398
 
280
399
 
281
 
bool drizzleclient_vio_peek_read(Vio *vio, uint32_t *bytes)
 
400
my_bool vio_peek_read(Vio *vio, uint *bytes)
282
401
{
 
402
#ifdef __WIN__
 
403
  int len;
 
404
  if (ioctlsocket(vio->sd, FIONREAD, &len))
 
405
    return TRUE;
 
406
  *bytes= len;
 
407
  return FALSE;
 
408
#elif FIONREAD_IN_SYS_IOCTL
 
409
  int len;
 
410
  if (ioctl(vio->sd, FIONREAD, &len) < 0)
 
411
    return TRUE;
 
412
  *bytes= len;
 
413
  return FALSE;
 
414
#else
283
415
  char buf[1024];
284
416
  ssize_t res= recv(vio->sd, &buf, sizeof(buf), MSG_PEEK);
285
 
 
286
417
  if (res < 0)
287
 
    return true;
288
 
  *bytes= (uint32_t)res;
289
 
  return false;
 
418
    return TRUE;
 
419
  *bytes= res;
 
420
  return FALSE;
 
421
#endif
290
422
}
291
423
 
292
 
void drizzleclient_vio_timeout(Vio *vio, bool is_sndtimeo, int32_t timeout)
 
424
void vio_timeout(Vio *vio, uint which, uint timeout)
293
425
{
294
 
  int error;
 
426
#if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO)
 
427
  int r;
 
428
  DBUG_ENTER("vio_timeout");
295
429
 
 
430
  {
 
431
#ifdef __WIN__
 
432
  /* Windows expects time in milliseconds as int */
 
433
  int wait_timeout= (int) timeout * 1000;
 
434
#else
296
435
  /* POSIX specifies time as struct timeval. */
297
436
  struct timeval wait_timeout;
298
437
  wait_timeout.tv_sec= timeout;
299
438
  wait_timeout.tv_usec= 0;
300
 
 
301
 
  assert(timeout >= 0 && timeout <= INT32_MAX);
302
 
  assert(vio->sd != -1);
303
 
  error= setsockopt(vio->sd, SOL_SOCKET, is_sndtimeo ? SO_SNDTIMEO : SO_RCVTIMEO,
304
 
                    &wait_timeout,
305
 
                    (socklen_t)sizeof(struct timeval));
306
 
  if (error == -1 && errno != ENOPROTOOPT)
307
 
  {
308
 
    perror("setsockopt");
309
 
    assert(error == 0);
310
 
  }
311
 
}
 
439
#endif
 
440
 
 
441
  r= setsockopt(vio->sd, SOL_SOCKET, which ? SO_SNDTIMEO : SO_RCVTIMEO,
 
442
                IF_WIN(const char*, const void*)&wait_timeout,
 
443
                sizeof(wait_timeout));
 
444
 
 
445
  }
 
446
 
 
447
#ifndef DBUG_OFF
 
448
  if (r != 0)
 
449
    DBUG_PRINT("error", ("setsockopt failed: %d, errno: %d", r, socket_errno));
 
450
#endif
 
451
 
 
452
  DBUG_VOID_RETURN;
 
453
#else
 
454
/*
 
455
  Platforms not suporting setting of socket timeout should either use
 
456
  thr_alarm or just run without read/write timeout(s)
 
457
*/
 
458
#endif
 
459
}
 
460
 
 
461
 
 
462
#ifdef __WIN__
 
463
size_t vio_read_pipe(Vio * vio, uchar* buf, size_t size)
 
464
{
 
465
  DWORD length;
 
466
  DBUG_ENTER("vio_read_pipe");
 
467
  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u", vio->sd, (long) buf,
 
468
                       (uint) size));
 
469
 
 
470
  if (!ReadFile(vio->hPipe, buf, size, &length, NULL))
 
471
    DBUG_RETURN(-1);
 
472
 
 
473
  DBUG_PRINT("exit", ("%d", length));
 
474
  DBUG_RETURN((size_t) length);
 
475
}
 
476
 
 
477
 
 
478
size_t vio_write_pipe(Vio * vio, const uchar* buf, size_t size)
 
479
{
 
480
  DWORD length;
 
481
  DBUG_ENTER("vio_write_pipe");
 
482
  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u", vio->sd, (long) buf,
 
483
                       (uint) size));
 
484
 
 
485
  if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL))
 
486
    DBUG_RETURN(-1);
 
487
 
 
488
  DBUG_PRINT("exit", ("%d", length));
 
489
  DBUG_RETURN((size_t) length);
 
490
}
 
491
 
 
492
int vio_close_pipe(Vio * vio)
 
493
{
 
494
  int r;
 
495
  DBUG_ENTER("vio_close_pipe");
 
496
#if defined(__NT__) && defined(MYSQL_SERVER)
 
497
  CancelIo(vio->hPipe);
 
498
  DisconnectNamedPipe(vio->hPipe);
 
499
#endif
 
500
  r=CloseHandle(vio->hPipe);
 
501
  if (r)
 
502
  {
 
503
    DBUG_PRINT("vio_error", ("close() failed, error: %d",GetLastError()));
 
504
    /* FIXME: error handling (not critical for MySQL) */
 
505
  }
 
506
  vio->type= VIO_CLOSED;
 
507
  vio->sd=   -1;
 
508
  DBUG_RETURN(r);
 
509
}
 
510
 
 
511
 
 
512
void vio_ignore_timeout(Vio *vio __attribute__((unused)),
 
513
                        uint which __attribute__((unused)),
 
514
                        uint timeout __attribute__((unused)))
 
515
{
 
516
}
 
517
 
 
518
 
 
519
#ifdef HAVE_SMEM
 
520
 
 
521
size_t vio_read_shared_memory(Vio * vio, uchar* buf, size_t size)
 
522
{
 
523
  size_t length;
 
524
  size_t remain_local;
 
525
  char *current_postion;
 
526
  DBUG_ENTER("vio_read_shared_memory");
 
527
  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %d", vio->sd, (long) buf,
 
528
                       size));
 
529
 
 
530
  remain_local = size;
 
531
  current_postion=buf;
 
532
  do
 
533
  {
 
534
    if (vio->shared_memory_remain == 0)
 
535
    {
 
536
      HANDLE events[2];
 
537
      events[0]= vio->event_server_wrote;
 
538
      events[1]= vio->event_conn_closed;
 
539
      /*
 
540
        WaitForMultipleObjects can return next values:
 
541
         WAIT_OBJECT_0+0 - event from vio->event_server_wrote
 
542
         WAIT_OBJECT_0+1 - event from vio->event_conn_closed. We can't read
 
543
                           anything
 
544
         WAIT_ABANDONED_0 and WAIT_TIMEOUT - fail.  We can't read anything
 
545
      */
 
546
      if (WaitForMultipleObjects(2, (HANDLE*)&events,FALSE,
 
547
                                 vio->net->read_timeout*1000) != WAIT_OBJECT_0)
 
548
      {
 
549
        DBUG_RETURN(-1);
 
550
      };
 
551
 
 
552
      vio->shared_memory_pos = vio->handle_map;
 
553
      vio->shared_memory_remain = uint4korr((ulong*)vio->shared_memory_pos);
 
554
      vio->shared_memory_pos+=4;
 
555
    }
 
556
 
 
557
    length = size;
 
558
 
 
559
    if (vio->shared_memory_remain < length)
 
560
       length = vio->shared_memory_remain;
 
561
    if (length > remain_local)
 
562
       length = remain_local;
 
563
 
 
564
    memcpy(current_postion,vio->shared_memory_pos,length);
 
565
 
 
566
    vio->shared_memory_remain-=length;
 
567
    vio->shared_memory_pos+=length;
 
568
    current_postion+=length;
 
569
    remain_local-=length;
 
570
 
 
571
    if (!vio->shared_memory_remain)
 
572
    {
 
573
      if (!SetEvent(vio->event_client_read))
 
574
        DBUG_RETURN(-1);
 
575
    }
 
576
  } while (remain_local);
 
577
  length = size;
 
578
 
 
579
  DBUG_PRINT("exit", ("%lu", (ulong) length));
 
580
  DBUG_RETURN(length);
 
581
}
 
582
 
 
583
 
 
584
size_t vio_write_shared_memory(Vio * vio, const uchar* buf, size_t size)
 
585
{
 
586
  size_t length, remain, sz;
 
587
  HANDLE pos;
 
588
  const uchar *current_postion;
 
589
  DBUG_ENTER("vio_write_shared_memory");
 
590
  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %d", vio->sd, (long) buf,
 
591
                       size));
 
592
 
 
593
  remain = size;
 
594
  current_postion = buf;
 
595
  while (remain != 0)
 
596
  {
 
597
    if (WaitForSingleObject(vio->event_server_read,
 
598
                            vio->net->write_timeout*1000) !=
 
599
        WAIT_OBJECT_0)
 
600
    {
 
601
      DBUG_RETURN((size_t) -1);
 
602
    }
 
603
 
 
604
    sz= (remain > shared_memory_buffer_length ? shared_memory_buffer_length :
 
605
         remain);
 
606
 
 
607
    int4store(vio->handle_map,sz);
 
608
    pos = vio->handle_map + 4;
 
609
    memcpy(pos,current_postion,sz);
 
610
    remain-=sz;
 
611
    current_postion+=sz;
 
612
    if (!SetEvent(vio->event_client_wrote))
 
613
      DBUG_RETURN((size_t) -1);
 
614
  }
 
615
  length = size;
 
616
 
 
617
  DBUG_PRINT("exit", ("%lu", (ulong) length));
 
618
  DBUG_RETURN(length);
 
619
}
 
620
 
 
621
 
 
622
/**
 
623
 Close shared memory and DBUG_PRINT any errors that happen on closing.
 
624
 @return Zero if all closing functions succeed, and nonzero otherwise.
 
625
*/
 
626
int vio_close_shared_memory(Vio * vio)
 
627
{
 
628
  int error_count= 0;
 
629
  DBUG_ENTER("vio_close_shared_memory");
 
630
  if (vio->type != VIO_CLOSED)
 
631
  {
 
632
    /*
 
633
      Set event_conn_closed for notification of both client and server that
 
634
      connection is closed
 
635
    */
 
636
    SetEvent(vio->event_conn_closed);
 
637
    /*
 
638
      Close all handlers. UnmapViewOfFile and CloseHandle return non-zero
 
639
      result if they are success.
 
640
    */
 
641
    if (UnmapViewOfFile(vio->handle_map) == 0) 
 
642
    {
 
643
      error_count++;
 
644
      DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed"));
 
645
    }
 
646
    if (CloseHandle(vio->event_server_wrote) == 0)
 
647
    {
 
648
      error_count++;
 
649
      DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed"));
 
650
    }
 
651
    if (CloseHandle(vio->event_server_read) == 0)
 
652
    {
 
653
      error_count++;
 
654
      DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed"));
 
655
    }
 
656
    if (CloseHandle(vio->event_client_wrote) == 0)
 
657
    {
 
658
      error_count++;
 
659
      DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed"));
 
660
    }
 
661
    if (CloseHandle(vio->event_client_read) == 0)
 
662
    {
 
663
      error_count++;
 
664
      DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed"));
 
665
    }
 
666
    if (CloseHandle(vio->handle_file_map) == 0)
 
667
    {
 
668
      error_count++;
 
669
      DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed"));
 
670
    }
 
671
    if (CloseHandle(vio->event_conn_closed) == 0)
 
672
    {
 
673
      error_count++;
 
674
      DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed"));
 
675
    }
 
676
  }
 
677
  vio->type= VIO_CLOSED;
 
678
  vio->sd=   -1;
 
679
  DBUG_RETURN(error_count);
 
680
}
 
681
#endif /* HAVE_SMEM */
 
682
#endif /* __WIN__ */