Drizzled Public API Documentation

vio.cc
00001 /* Copyright (C) 2000 MySQL AB
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software
00014    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00015 
00016 /*
00017   Note that we can't have assertion on file descriptors;  The reason for
00018   this is that during mysql shutdown, another thread can close a file
00019   we are working on.  In this case we should just return read errors from
00020   the file descriptior.
00021 */
00022 #include <config.h>
00023 #include "vio.h"
00024 #include <string.h>
00025 #include <drizzled/util/test.h>
00026 #include <sys/socket.h>
00027 #include <string.h>
00028 #include <sys/types.h>
00029 #include <netinet/tcp.h>
00030 #include <netinet/in.h>
00031 #include <sys/poll.h>
00032 #include <unistd.h>
00033 #include <fcntl.h>
00034 #include <netdb.h>
00035 #include <algorithm>
00036 #include <cstdlib>
00037 #include <cassert>
00038 #include <cstdio>
00039 #include <fcntl.h>
00040 
00041 using namespace std;
00042 
00043 namespace drizzle_plugin {
00044 
00045 Vio::Vio(int nsd) :
00046   sd(nsd)
00047 {
00048   /*
00049     We call fcntl() to set the flags and then immediately read them back
00050     to make sure that we and the system are in agreement on the state of
00051     things.
00052 
00053     An example of why we need to do this is FreeBSD (and apparently some
00054     other BSD-derived systems, like Mac OS X), where the system sometimes
00055     reports that the socket is set for non-blocking when it really will
00056     block.
00057   */
00058   fcntl(sd, F_SETFL, 0);
00059   fcntl_mode= fcntl(sd, F_GETFL);
00060 }
00061 
00062 Vio::~Vio()
00063 {
00064   close();
00065 }
00066 
00067 int Vio::close()
00068 {
00069   int r= 0;
00070   if (sd != -1)
00071   {
00072     assert(sd >= 0);
00073     if (shutdown(sd, SHUT_RDWR))
00074       r= -1;
00075     if (::close(sd))
00076       r= -1;
00077     sd=   -1;
00078   }
00079   return r;
00080 }
00081 
00082 size_t Vio::read(unsigned char* buf, size_t size)
00083 {
00084   return ::read(sd, buf, size);
00085 }
00086 
00087 size_t Vio::write(const unsigned char* buf, size_t size)
00088 {
00089   return ::write(sd, buf, size);
00090 }
00091 
00092 int Vio::blocking(bool set_blocking_mode, bool *old_mode)
00093 {
00094   int r=0;
00095 
00096   // make sure ptr is not NULL:
00097   if (NULL != old_mode)
00098     *old_mode= drizzled::test(!(fcntl_mode & O_NONBLOCK));
00099 
00100   if (sd >= 0)
00101   {
00102     int old_fcntl=fcntl_mode;
00103     if (set_blocking_mode)
00104       fcntl_mode &= ~O_NONBLOCK; /* clear bit */
00105     else
00106       fcntl_mode |= O_NONBLOCK; /* set bit */
00107     if (old_fcntl != fcntl_mode)
00108     {
00109       r= fcntl(sd, F_SETFL, fcntl_mode);
00110       if (r == -1)
00111       {
00112         fcntl_mode= old_fcntl;
00113       }
00114     }
00115   }
00116 
00117   return r;
00118 }
00119 
00120 int Vio::fastsend()
00121 {
00122   int nodelay = 1;
00123   int error= setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay));
00124   if (error)
00125     perror("setsockopt");
00126   return error;
00127 }
00128 
00129 int32_t Vio::keepalive(bool set_keep_alive)
00130 {
00131   uint32_t opt= set_keep_alive;
00132   int r= setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
00133   if (r)
00134   {
00135     perror("setsockopt");
00136     assert(false);
00137   }
00138   return r;
00139 }
00140 
00141 bool Vio::should_retry() const
00142 {
00143   int en = errno;
00144   return en == EAGAIN || en == EINTR || en == EWOULDBLOCK;
00145 }
00146 
00147 bool Vio::was_interrupted() const
00148 {
00149   int en= errno;
00150   return en == EAGAIN || en == EINTR || en == EWOULDBLOCK || en == ETIMEDOUT;
00151 }
00152 
00153 bool Vio::peer_addr(char *buf, size_t buflen, uint16_t& port) const
00154 {
00155   char port_buf[NI_MAXSERV];
00156   sockaddr_storage remote;
00157   socklen_t al = sizeof(remote);
00158 
00159   if (getpeername(sd, (sockaddr *) (&remote), &al) != 0)
00160     return true;
00161 
00162   if (getnameinfo((struct sockaddr *)(&remote), al, buf, buflen, port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV))
00163   {
00164     return true;
00165   }
00166 
00167   port= (uint16_t)strtol(port_buf, (char **)NULL, 10);
00168 
00169   return false;
00170 }
00171 
00172 void Vio::timeout(bool is_sndtimeo, int32_t t)
00173 {
00174   timeval wait_timeout;
00175   wait_timeout.tv_sec= t;
00176   wait_timeout.tv_usec= 0;
00177 
00178   assert(t >= 0 && t <= INT32_MAX);
00179   assert(sd != -1);
00180   int error= setsockopt(sd, SOL_SOCKET, is_sndtimeo ? SO_SNDTIMEO : SO_RCVTIMEO, &wait_timeout,
00181                     (socklen_t)sizeof(struct timeval));
00182   if (error == -1 && errno != ENOPROTOOPT)
00183   {
00184     perror("setsockopt");
00185     assert(error == 0);
00186   }
00187 }
00188 
00189 int Vio::get_errno() const
00190 {
00191   return errno;
00192 }
00193 
00194 int Vio::get_fd() const
00195 {
00196   return sd;
00197 }
00198 
00199 } /* namespace drizzle_plugin */