Drizzled Public API Documentation

vio.cc
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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 #include <config.h>
23 #include "vio.h"
24 #include <string.h>
25 #include <drizzled/util/test.h>
26 #include <sys/socket.h>
27 #include <string.h>
28 #include <sys/types.h>
29 #include <netinet/tcp.h>
30 #include <netinet/in.h>
31 #include <sys/poll.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <netdb.h>
35 #include <algorithm>
36 #include <cstdlib>
37 #include <cassert>
38 #include <cstdio>
39 #include <fcntl.h>
40 
41 using namespace std;
42 
43 namespace drizzle_plugin {
44 
45 Vio::Vio(int nsd) :
46  sd(nsd)
47 {
48  /*
49  We call fcntl() to set the flags and then immediately read them back
50  to make sure that we and the system are in agreement on the state of
51  things.
52 
53  An example of why we need to do this is FreeBSD (and apparently some
54  other BSD-derived systems, like Mac OS X), where the system sometimes
55  reports that the socket is set for non-blocking when it really will
56  block.
57  */
58  fcntl(sd, F_SETFL, 0);
59  fcntl_mode= fcntl(sd, F_GETFL);
60 }
61 
62 Vio::~Vio()
63 {
64  close();
65 }
66 
68 {
69  int r= 0;
70  if (sd != -1)
71  {
72  assert(sd >= 0);
73  if (shutdown(sd, SHUT_RDWR))
74  r= -1;
75  if (::close(sd))
76  r= -1;
77  sd= -1;
78  }
79  return r;
80 }
81 
82 size_t Vio::read(unsigned char* buf, size_t size)
83 {
84  return ::read(sd, buf, size);
85 }
86 
87 size_t Vio::write(const unsigned char* buf, size_t size)
88 {
89  return ::write(sd, buf, size);
90 }
91 
92 int Vio::blocking(bool set_blocking_mode, bool *old_mode)
93 {
94  int r=0;
95 
96  // make sure ptr is not NULL:
97  if (NULL != old_mode)
98  *old_mode= drizzled::test(!(fcntl_mode & O_NONBLOCK));
99 
100  if (sd >= 0)
101  {
102  int old_fcntl=fcntl_mode;
103  if (set_blocking_mode)
104  fcntl_mode &= ~O_NONBLOCK; /* clear bit */
105  else
106  fcntl_mode |= O_NONBLOCK; /* set bit */
107  if (old_fcntl != fcntl_mode)
108  {
109  r= fcntl(sd, F_SETFL, fcntl_mode);
110  if (r == -1)
111  {
112  fcntl_mode= old_fcntl;
113  }
114  }
115  }
116 
117  return r;
118 }
119 
121 {
122  int nodelay = 1;
123  int error= setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay));
124  if (error)
125  perror("setsockopt");
126  return error;
127 }
128 
129 int32_t Vio::keepalive(bool set_keep_alive)
130 {
131  uint32_t opt= set_keep_alive;
132  int r= setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
133  if (r)
134  {
135  perror("setsockopt");
136  assert(false);
137  }
138  return r;
139 }
140 
141 bool Vio::should_retry() const
142 {
143  int en = errno;
144  return en == EAGAIN || en == EINTR || en == EWOULDBLOCK;
145 }
146 
148 {
149  int en= errno;
150  return en == EAGAIN || en == EINTR || en == EWOULDBLOCK || en == ETIMEDOUT;
151 }
152 
153 bool Vio::peer_addr(char *buf, size_t buflen, uint16_t& port) const
154 {
155  char port_buf[NI_MAXSERV];
156  sockaddr_storage remote;
157  socklen_t al = sizeof(remote);
158 
159  if (getpeername(sd, (sockaddr *) (&remote), &al) != 0)
160  return true;
161 
162  if (getnameinfo((struct sockaddr *)(&remote), al, buf, buflen, port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV))
163  {
164  return true;
165  }
166 
167  port= (uint16_t)strtol(port_buf, (char **)NULL, 10);
168 
169  return false;
170 }
171 
172 void Vio::timeout(bool is_sndtimeo, int32_t t)
173 {
174  timeval wait_timeout;
175  wait_timeout.tv_sec= t;
176  wait_timeout.tv_usec= 0;
177 
178  assert(t >= 0 && t <= INT32_MAX);
179  assert(sd != -1);
180  int error= setsockopt(sd, SOL_SOCKET, is_sndtimeo ? SO_SNDTIMEO : SO_RCVTIMEO, &wait_timeout,
181  (socklen_t)sizeof(struct timeval));
182  if (error == -1 && errno != ENOPROTOOPT)
183  {
184  perror("setsockopt");
185  assert(error == 0);
186  }
187 }
188 
189 int Vio::get_errno() const
190 {
191  return errno;
192 }
193 
194 int Vio::get_fd() const
195 {
196  return sd;
197 }
198 
199 } /* namespace drizzle_plugin */