~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to vio/viosocket.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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"
 
24
 
 
25
int vio_errno(Vio *vio __attribute__((unused)))
 
26
{
 
27
  return socket_errno;          /* On Win32 this mapped to WSAGetLastError() */
 
28
}
 
29
 
 
30
 
 
31
size_t vio_read(Vio * vio, uchar* buf, size_t size)
 
32
{
 
33
  size_t 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);
 
54
}
 
55
 
 
56
 
 
57
/*
 
58
  Buffered read: if average read size is small it may
 
59
  reduce number of syscalls.
 
60
*/
 
61
 
 
62
size_t vio_read_buff(Vio *vio, uchar* buf, size_t size)
 
63
{
 
64
  size_t rc;
 
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));
 
69
 
 
70
  if (vio->read_pos < vio->read_end)
 
71
  {
 
72
    rc= min((size_t) (vio->read_end - vio->read_pos), size);
 
73
    memcpy(buf, vio->read_pos, rc);
 
74
    vio->read_pos+= rc;
 
75
    /*
 
76
      Do not try to read from the socket now even if rc < size:
 
77
      vio_read can return -1 due to an error or non-blocking mode, and
 
78
      the safest way to handle it is to move to a separate branch.
 
79
    */
 
80
  }
 
81
  else if (size < VIO_UNBUFFERED_READ_MIN_SIZE)
 
82
  {
 
83
    rc= vio_read(vio, (uchar*) vio->read_buffer, VIO_READ_BUFFER_SIZE);
 
84
    if (rc != 0 && rc != (size_t) -1)
 
85
    {
 
86
      if (rc > size)
 
87
      {
 
88
        vio->read_pos= vio->read_buffer + size;
 
89
        vio->read_end= vio->read_buffer + rc;
 
90
        rc= size;
 
91
      }
 
92
      memcpy(buf, vio->read_buffer, rc);
 
93
    }
 
94
  }
 
95
  else
 
96
    rc= vio_read(vio, buf, size);
 
97
  DBUG_RETURN(rc);
 
98
#undef VIO_UNBUFFERED_READ_MIN_SIZE
 
99
}
 
100
 
 
101
 
 
102
size_t vio_write(Vio * vio, const uchar* buf, size_t size)
 
103
{
 
104
  size_t r;
 
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
 
111
  r = write(vio->sd, buf, size);
 
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);
 
121
}
 
122
 
 
123
int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode,
 
124
                 my_bool *old_mode)
 
125
{
 
126
  int r=0;
 
127
  DBUG_ENTER("vio_blocking");
 
128
 
 
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));
 
132
 
 
133
#if !defined(__WIN__)
 
134
#if !defined(NO_FCNTL_NONBLOCK)
 
135
  if (vio->sd >= 0)
 
136
  {
 
137
    int old_fcntl=vio->fcntl_mode;
 
138
    if (set_blocking_mode)
 
139
      vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
 
140
    else
 
141
      vio->fcntl_mode |= O_NONBLOCK; /* set bit */
 
142
    if (old_fcntl != vio->fcntl_mode)
 
143
    {
 
144
      r= fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
 
145
      if (r == -1)
 
146
      {
 
147
        DBUG_PRINT("info", ("fcntl failed, errno %d", errno));
 
148
        vio->fcntl_mode= old_fcntl;
 
149
      }
 
150
    }
 
151
  }
 
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);
 
178
}
 
179
 
 
180
my_bool
 
181
vio_is_blocking(Vio * vio)
 
182
{
 
183
  my_bool r;
 
184
  DBUG_ENTER("vio_is_blocking");
 
185
  r = !(vio->fcntl_mode & O_NONBLOCK);
 
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__ */
 
275
 if (vio->type != VIO_CLOSED)
 
276
  {
 
277
    DBUG_ASSERT(vio->sd >= 0);
 
278
    if (shutdown(vio->sd, SHUT_RDWR))
 
279
      r= -1;
 
280
    if (closesocket(vio->sd))
 
281
      r= -1;
 
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
  }
 
288
  vio->type= VIO_CLOSED;
 
289
  vio->sd=   -1;
 
290
  DBUG_RETURN(r);
 
291
}
 
292
 
 
293
 
 
294
const char *vio_description(Vio * vio)
 
295
{
 
296
  return vio->desc;
 
297
}
 
298
 
 
299
enum enum_vio_type vio_type(Vio* vio)
 
300
{
 
301
  return vio->type;
 
302
}
 
303
 
 
304
my_socket vio_fd(Vio* vio)
 
305
{
 
306
  return vio->sd;
 
307
}
 
308
 
 
309
my_bool vio_peer_addr(Vio *vio, char *buf, uint16 *port, size_t buflen)
 
310
{
 
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);
 
356
}
 
357
 
 
358
 
 
359
/* Return 0 if there is data to be read */
 
360
 
 
361
my_bool vio_poll_read(Vio *vio,uint timeout)
 
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)
 
383
  struct pollfd fds;
 
384
  int res;
 
385
  DBUG_ENTER("vio_poll");
 
386
  fds.fd=vio->sd;
 
387
  fds.events=POLLIN;
 
388
  fds.revents=0;
 
389
  if ((res=poll(&fds,1,(int) timeout*1000)) <= 0)
 
390
  {
 
391
    DBUG_RETURN(res < 0 ? 0 : 1);               /* Don't return 1 on errors */
 
392
  }
 
393
  DBUG_RETURN(fds.revents & (POLLIN | POLLERR | POLLHUP) ? 0 : 1);
 
394
#else
 
395
  return 0;
 
396
#endif
 
397
}
 
398
 
 
399
 
 
400
my_bool vio_peek_read(Vio *vio, uint *bytes)
 
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
 
415
  char buf[1024];
 
416
  ssize_t res= recv(vio->sd, &buf, sizeof(buf), MSG_PEEK);
 
417
  if (res < 0)
 
418
    return TRUE;
 
419
  *bytes= res;
 
420
  return FALSE;
 
421
#endif
 
422
}
 
423
 
 
424
void vio_timeout(Vio *vio, uint which, uint timeout)
 
425
{
 
426
#if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO)
 
427
  int r;
 
428
  DBUG_ENTER("vio_timeout");
 
429
 
 
430
  {
 
431
#ifdef __WIN__
 
432
  /* Windows expects time in milliseconds as int */
 
433
  int wait_timeout= (int) timeout * 1000;
 
434
#else
 
435
  /* POSIX specifies time as struct timeval. */
 
436
  struct timeval wait_timeout;
 
437
  wait_timeout.tv_sec= timeout;
 
438
  wait_timeout.tv_usec= 0;
 
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__ */