violite.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:10k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This library is free software; you can redistribute it and/or
  4.    modify it under the terms of the GNU Library General Public
  5.    License as published by the Free Software Foundation; either
  6.    version 2 of the License, or (at your option) any later version.
  7.    
  8.    This library is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.    Library General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU Library General Public
  14.    License along with this library; if not, write to the Free
  15.    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  16.    MA 02111-1307, USA */
  17. /*
  18.   Note that we can't have assertion on file descriptors;  The reason for
  19.   this is that during mysql shutdown, another thread can close a file
  20.   we are working on.  In this case we should just return read errors from
  21.   the file descriptior.
  22. */
  23. #include <global.h>
  24. #ifndef HAVE_VIO /* is Vio suppored by the Vio lib ? */
  25. #include <errno.h>
  26. #include <assert.h>
  27. #include <violite.h>
  28. #include <my_sys.h>
  29. #include <my_net.h>
  30. #include <m_string.h>
  31. #ifdef HAVE_POLL
  32. #include <sys/poll.h>
  33. #endif
  34. #ifdef HAVE_SYS_IOCTL_H
  35. #include <sys/ioctl.h>
  36. #endif
  37. #if defined(__EMX__)
  38. #define ioctlsocket ioctl
  39. #endif /* defined(__EMX__) */
  40. #if defined(MSDOS) || defined(__WIN__)
  41. #ifdef __WIN__
  42. #undef errno
  43. #undef EINTR
  44. #undef EAGAIN
  45. #define errno WSAGetLastError()
  46. #define EINTR  WSAEINTR
  47. #define EAGAIN WSAEINPROGRESS
  48. #endif /* __WIN__ */
  49. #define O_NONBLOCK 1    /* For emulation of fcntl() */
  50. #endif
  51. #ifndef EWOULDBLOCK
  52. #define EWOULDBLOCK EAGAIN
  53. #endif
  54. #ifndef __WIN__
  55. #define HANDLE void *
  56. #endif
  57. struct st_vio
  58. {
  59.   my_socket sd; /* my_socket - real or imaginary */
  60.   HANDLE hPipe;
  61.   my_bool localhost; /* Are we from localhost? */
  62.   int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */
  63.   struct sockaddr_in local; /* Local internet address */
  64.   struct sockaddr_in remote; /* Remote internet address */
  65.   enum enum_vio_type type; /* Type of connection */
  66.   char desc[30]; /* String description */
  67. };
  68. typedef void *vio_ptr;
  69. typedef char *vio_cstring;
  70. /*
  71.  * Helper to fill most of the Vio* with defaults.
  72.  */
  73. static void vio_reset(Vio* vio, enum enum_vio_type type,
  74.       my_socket sd, HANDLE hPipe,
  75.       my_bool localhost)
  76. {
  77.   bzero((char*) vio, sizeof(*vio));
  78.   vio->type = type;
  79.   vio->sd = sd;
  80.   vio->hPipe = hPipe;
  81.   vio->localhost= localhost;
  82. }
  83. /* Open the socket or TCP/IP connection and read the fnctl() status */
  84. Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost)
  85. {
  86.   Vio *vio;
  87.   DBUG_ENTER("vio_new");
  88.   DBUG_PRINT("enter", ("sd=%d", sd));
  89.   if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME))))
  90.   {
  91.     vio_reset(vio, type, sd, 0, localhost);
  92.     sprintf(vio->desc,
  93.     (vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"),
  94.     vio->sd);
  95. #if !defined(___WIN__) && !defined(__EMX__)
  96. #if !defined(NO_FCNTL_NONBLOCK)
  97.     vio->fcntl_mode = fcntl(sd, F_GETFL);
  98. #elif defined(HAVE_SYS_IOCTL_H) /* hpux */
  99.     /* Non blocking sockets doesn't work good on HPUX 11.0 */
  100.     (void) ioctl(sd,FIOSNBIO,0);
  101. #endif
  102. #else /* !defined(__WIN__) && !defined(__EMX__) */
  103.     {
  104.       /* set to blocking mode by default */
  105.       ulong arg=0, r;
  106.       r = ioctlsocket(sd,FIONBIO,(void*) &arg, sizeof(arg));
  107.     }
  108. #endif
  109.   }
  110.   DBUG_RETURN(vio);
  111. }
  112. #ifdef __WIN__
  113. Vio *vio_new_win32pipe(HANDLE hPipe)
  114. {
  115.   Vio *vio;
  116.   DBUG_ENTER("vio_new_handle");
  117.   if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
  118.   {
  119.     vio_reset(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, TRUE);
  120.     strmov(vio->desc, "named pipe");
  121.   }
  122.   DBUG_RETURN(vio);
  123. }
  124. #endif
  125. void vio_delete(Vio * vio)
  126. {
  127.   /* It must be safe to delete null pointers. */
  128.   /* This matches the semantics of C++'s delete operator. */
  129.   if (vio)
  130.   {
  131.     if (vio->type != VIO_CLOSED)
  132.       vio_close(vio);
  133.     my_free((gptr) vio,MYF(0));
  134.   }
  135. }
  136. int vio_errno(Vio *vio __attribute__((unused)))
  137. {
  138.   return errno; /* On Win32 this mapped to WSAGetLastError() */
  139. }
  140. int vio_read(Vio * vio, gptr buf, int size)
  141. {
  142.   int r;
  143.   DBUG_ENTER("vio_read");
  144.   DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
  145. #ifdef __WIN__
  146.   if (vio->type == VIO_TYPE_NAMEDPIPE)
  147.   {
  148.     DWORD length;
  149.     if (!ReadFile(vio->hPipe, buf, size, &length, NULL))
  150.       DBUG_RETURN(-1);
  151.     DBUG_RETURN(length);
  152.   }
  153.   r = recv(vio->sd, buf, size,0);
  154. #else
  155.   errno=0; /* For linux */
  156.   r = read(vio->sd, buf, size);
  157. #endif /* __WIN__ */
  158. #ifndef DBUG_OFF
  159.   if (r < 0)
  160.   {
  161.     DBUG_PRINT("error", ("Got error %d during read",errno));
  162.   }
  163. #endif /* DBUG_OFF */
  164.   DBUG_PRINT("exit", ("%d", r));
  165.   DBUG_RETURN(r);
  166. }
  167. int vio_write(Vio * vio, const gptr buf, int size)
  168. {
  169.   int r;
  170.   DBUG_ENTER("vio_write");
  171.   DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
  172. #ifdef __WIN__
  173.   if ( vio->type == VIO_TYPE_NAMEDPIPE)
  174.   {
  175.     DWORD length;
  176.     if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL))
  177.       DBUG_RETURN(-1);
  178.     DBUG_RETURN(length);
  179.   }
  180.   r = send(vio->sd, buf, size,0);
  181. #else
  182.   r = write(vio->sd, buf, size);
  183. #endif /* __WIN__ */
  184. #ifndef DBUG_OFF
  185.   if (r < 0)
  186.   {
  187.     DBUG_PRINT("error", ("Got error on write: %d",errno));
  188.   }
  189. #endif /* DBUG_OFF */
  190.   DBUG_PRINT("exit", ("%d", r));
  191.   DBUG_RETURN(r);
  192. }
  193. int vio_blocking(Vio * vio, my_bool set_blocking_mode)
  194. {
  195.   int r=0;
  196.   DBUG_ENTER("vio_blocking");
  197.   DBUG_PRINT("enter", ("set_blocking_mode: %d", (int) set_blocking_mode));
  198. #if !defined(___WIN__) && !defined(__EMX__)
  199. #if !defined(NO_FCNTL_NONBLOCK)
  200.   if (vio->sd >= 0)
  201.   {
  202.     int old_fcntl=vio->fcntl_mode;
  203.     if (set_blocking_mode)
  204.       vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
  205.     else
  206.       vio->fcntl_mode |= O_NONBLOCK; /* set bit */
  207.     if (old_fcntl != vio->fcntl_mode)
  208.       r = fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
  209.   }
  210. #endif /* !defined(NO_FCNTL_NONBLOCK) */
  211. #else /* !defined(__WIN__) && !defined(__EMX__) */
  212. #ifndef __EMX__
  213.   if (vio->type != VIO_TYPE_NAMEDPIPE)  
  214. #endif
  215.   { 
  216.     ulong arg;
  217.     int old_fcntl=vio->fcntl_mode;
  218.     if (set_blocking_mode)
  219.     {
  220.       arg = 0;
  221.       vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
  222.     }
  223.     else
  224.     {
  225.       arg = 1;
  226.       vio->fcntl_mode |= O_NONBLOCK; /* set bit */
  227.     }
  228.     if (old_fcntl != vio->fcntl_mode)
  229.       r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg, sizeof(arg));
  230.   }
  231. #endif /* !defined(__WIN__) && !defined(__EMX__) */
  232.   DBUG_RETURN(r);
  233. }
  234. my_bool
  235. vio_is_blocking(Vio * vio)
  236. {
  237.   my_bool r;
  238.   DBUG_ENTER("vio_is_blocking");
  239.   r = !(vio->fcntl_mode & O_NONBLOCK);
  240.   DBUG_PRINT("exit", ("%d", (int) r));
  241.   DBUG_RETURN(r);
  242. }
  243. int vio_fastsend(Vio * vio __attribute__((unused)))
  244. {
  245.   int r=0;
  246.   DBUG_ENTER("vio_fastsend");
  247. #ifdef IPTOS_THROUGHPUT
  248.   {
  249. #ifndef __EMX__
  250.     int tos = IPTOS_THROUGHPUT;
  251.     if (!setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos)))
  252. #endif /* !__EMX__ */
  253.     {
  254.       int nodelay = 1;
  255.       if (setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void *) &nodelay,
  256.      sizeof(nodelay))) {
  257. DBUG_PRINT("warning",
  258.    ("Couldn't set socket option for fast send"));
  259. r= -1;
  260.       }
  261.     }
  262.   }
  263. #endif /* IPTOS_THROUGHPUT */
  264.   DBUG_PRINT("exit", ("%d", r));
  265.   DBUG_RETURN(r);
  266. }
  267. int vio_keepalive(Vio* vio, my_bool set_keep_alive)
  268. {
  269.   int r=0;
  270.   uint opt = 0;
  271.   DBUG_ENTER("vio_keepalive");
  272.   DBUG_PRINT("enter", ("sd=%d, set_keep_alive=%d", vio->sd, (int)
  273.        set_keep_alive));
  274.   if (vio->type != VIO_TYPE_NAMEDPIPE)
  275.   {
  276.     if (set_keep_alive)
  277.       opt = 1;
  278.     r = setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
  279.    sizeof(opt));
  280.   }
  281.   DBUG_RETURN(r);
  282. }
  283. my_bool
  284. vio_should_retry(Vio * vio __attribute__((unused)))
  285. {
  286.   int en = errno;
  287.   return en == EAGAIN || en == EINTR || en == EWOULDBLOCK;
  288. }
  289. int vio_close(Vio * vio)
  290. {
  291.   int r;
  292.   DBUG_ENTER("vio_close");
  293. #ifdef __WIN__
  294.   if (vio->type == VIO_TYPE_NAMEDPIPE)
  295.   {
  296. #if defined(__NT__) && defined(MYSQL_SERVER)
  297.     CancelIo(vio->hPipe);
  298.     DisconnectNamedPipe(vio->hPipe);
  299. #endif
  300.     r=CloseHandle(vio->hPipe);
  301.   }
  302.   else if (vio->type != VIO_CLOSED)
  303. #endif /* __WIN__ */
  304.   {
  305.     r=0;
  306.     if (shutdown(vio->sd,2))
  307.       r= -1;
  308.     if (closesocket(vio->sd))
  309.       r= -1;
  310.   }
  311.   if (r)
  312.   {
  313.     DBUG_PRINT("error", ("close() failed, error: %d",errno));
  314.     /* FIXME: error handling (not critical for MySQL) */
  315.   }
  316.   vio->type= VIO_CLOSED;
  317.   vio->sd=   -1;
  318.   DBUG_RETURN(r);
  319. }
  320. const char *vio_description(Vio * vio)
  321. {
  322.   return vio->desc;
  323. }
  324. enum enum_vio_type vio_type(Vio* vio)
  325. {
  326.   return vio->type;
  327. }
  328. my_socket vio_fd(Vio* vio)
  329. {
  330.   return vio->sd;
  331. }
  332. my_bool vio_peer_addr(Vio * vio, char *buf)
  333. {
  334.   DBUG_ENTER("vio_peer_addr");
  335.   DBUG_PRINT("enter", ("sd=%d", vio->sd));
  336.   if (vio->localhost)
  337.   {
  338.     strmov(buf,"127.0.0.1");
  339.   }
  340.   else
  341.   {
  342.     size_socket addrLen = sizeof(struct sockaddr);
  343.     if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)),
  344.     &addrLen) != 0)
  345.     {
  346.       DBUG_PRINT("exit", ("getpeername, error: %d", errno));
  347.       DBUG_RETURN(1);
  348.     }
  349.     my_inet_ntoa(vio->remote.sin_addr,buf);
  350.   }
  351.   DBUG_PRINT("exit", ("addr=%s", buf));
  352.   DBUG_RETURN(0);
  353. }
  354. void vio_in_addr(Vio *vio, struct in_addr *in)
  355. {
  356.   DBUG_ENTER("vio_in_addr");
  357.   if (vio->localhost)
  358.     bzero((char*) in, sizeof(*in)); /* This should never be executed */
  359.   else
  360.     *in=vio->remote.sin_addr;
  361.   DBUG_VOID_RETURN;
  362. }
  363. /* Return 0 if there is data to be read */
  364. my_bool vio_poll_read(Vio *vio,uint timeout)
  365. {
  366. #ifndef HAVE_POLL
  367.   return 0;
  368. #else
  369.   struct pollfd fds;
  370.   int res;
  371.   DBUG_ENTER("vio_poll");
  372.   fds.fd=vio->sd;
  373.   fds.events=POLLIN;
  374.   fds.revents=0;
  375.   if ((res=poll(&fds,1,(int) timeout*1000)) <= 0)
  376.   {
  377.     DBUG_RETURN(res < 0 ? 0 : 1); /* Don't return 1 on errors */
  378.   }
  379.   DBUG_RETURN(fds.revents & POLLIN ? 0 : 1);
  380. #endif
  381. }
  382. #endif /* HAVE_VIO */