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

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