home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / sql / violite.c < prev   
C/C++ Source or Header  |  2000-11-14  |  10KB  |  428 lines

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