~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/mysql_protocol/vio.cc

  • Committer: patrick crews
  • Date: 2010-09-29 15:15:19 UTC
  • mfrom: (1099.4.188 drizzle)
  • Revision ID: gleebix@gmail.com-20100929151519-6mrmzd1ciw2p9nws
Tags: 2010.09.1802
Update translations

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
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 */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
/*
17
17
  Note that we can't have assertion on file descriptors;  The reason for
19
19
  we are working on.  In this case we should just return read errors from
20
20
  the file descriptior.
21
21
*/
 
22
 
22
23
#include "config.h"
23
24
#include "vio.h"
24
25
#include <string.h>
40
41
 
41
42
using namespace std;
42
43
 
43
 
namespace drizzle_plugin
44
 
{
45
 
 
46
 
Vio::Vio(int nsd) :
47
 
  closed(false),
48
 
  sd(nsd),
49
 
  fcntl_mode(0),
50
 
  local(),
51
 
  remote(),
52
 
  read_pos(NULL),
53
 
  read_end(NULL)
54
 
{
55
 
  /*
56
 
    We call fcntl() to set the flags and then immediately read them back
57
 
    to make sure that we and the system are in agreement on the state of
58
 
    things.
59
 
 
60
 
    An example of why we need to do this is FreeBSD (and apparently some
61
 
    other BSD-derived systems, like Mac OS X), where the system sometimes
62
 
    reports that the socket is set for non-blocking when it really will
63
 
    block.
64
 
  */
65
 
  fcntl(sd, F_SETFL, 0);
66
 
  fcntl_mode= fcntl(sd, F_GETFL);
67
 
}
68
 
 
69
 
Vio::~Vio()
70
 
{
71
 
 if (!closed)
72
 
    close();
73
 
}
74
 
 
75
 
int Vio::close()
76
 
{
77
 
  int r=0;
78
 
  if (!closed)
79
 
  {
80
 
    assert(sd >= 0);
81
 
    if (shutdown(sd, SHUT_RDWR))
82
 
      r= -1;
83
 
    if (::close(sd))
84
 
      r= -1;
85
 
  }
86
 
  closed= true;
87
 
  sd=   -1;
88
 
 
89
 
  return r;
90
 
}
91
 
 
92
 
size_t Vio::read(unsigned char* buf, size_t size)
 
44
static void _vio_delete(Vio* vio)
 
45
{
 
46
  if (!vio)
 
47
    return; /* It must be safe to delete null pointers. */
 
48
 
 
49
  if (!vio->closed)
 
50
    vio->vioclose(vio);
 
51
  free((unsigned char*) vio);
 
52
}
 
53
 
 
54
static int _vio_errno(Vio *vio)
 
55
{
 
56
  (void)vio;
 
57
  return errno;
 
58
}
 
59
 
 
60
static size_t _vio_read(Vio * vio, unsigned char* buf, size_t size)
93
61
{
94
62
  size_t r;
95
63
 
96
64
  /* Ensure nobody uses vio_read_buff and vio_read simultaneously */
97
 
  assert(read_end == read_pos);
98
 
  r= ::read(sd, buf, size);
 
65
  assert(vio->read_end == vio->read_pos);
 
66
  r= read(vio->sd, buf, size);
99
67
 
100
68
  return r;
101
69
}
102
70
 
103
 
size_t Vio::write(const unsigned char* buf, size_t size)
 
71
static size_t _vio_write(Vio * vio, const unsigned char* buf, size_t size)
104
72
{
105
73
  size_t r;
106
74
 
107
 
  r = ::write(sd, buf, size);
 
75
  r = write(vio->sd, buf, size);
108
76
 
109
77
  return r;
110
78
}
111
79
 
112
 
int Vio::blocking(bool set_blocking_mode, bool *old_mode)
 
80
static int _vio_blocking(Vio * vio, bool set_blocking_mode, bool *old_mode)
113
81
{
114
82
  int r=0;
115
83
 
116
 
  // make sure ptr is not NULL:
117
 
  if (NULL != old_mode)
118
 
    *old_mode= drizzled::test(!(fcntl_mode & O_NONBLOCK));
 
84
  *old_mode= drizzled::test(!(vio->fcntl_mode & O_NONBLOCK));
119
85
 
120
 
  if (sd >= 0)
 
86
  if (vio->sd >= 0)
121
87
  {
122
 
    int old_fcntl=fcntl_mode;
 
88
    int old_fcntl=vio->fcntl_mode;
123
89
    if (set_blocking_mode)
124
 
      fcntl_mode &= ~O_NONBLOCK; /* clear bit */
 
90
      vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
125
91
    else
126
 
      fcntl_mode |= O_NONBLOCK; /* set bit */
127
 
    if (old_fcntl != fcntl_mode)
 
92
      vio->fcntl_mode |= O_NONBLOCK; /* set bit */
 
93
    if (old_fcntl != vio->fcntl_mode)
128
94
    {
129
 
      r= fcntl(sd, F_SETFL, fcntl_mode);
 
95
      r= fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
130
96
      if (r == -1)
131
97
      {
132
 
        fcntl_mode= old_fcntl;
 
98
        vio->fcntl_mode= old_fcntl;
133
99
      }
134
100
    }
135
101
  }
137
103
  return r;
138
104
}
139
105
 
140
 
int Vio::fastsend()
 
106
static int _vio_fastsend(Vio * vio)
141
107
{
 
108
  (void)vio;
142
109
  int nodelay = 1;
143
110
  int error;
144
111
 
145
 
  error= setsockopt(sd, IPPROTO_TCP, TCP_NODELAY,
 
112
  error= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY,
146
113
                    &nodelay, sizeof(nodelay));
147
114
  if (error != 0)
148
115
  {
149
116
    perror("setsockopt");
 
117
    assert(error == 0);
150
118
  }
151
119
 
152
120
  return error;
153
121
}
154
122
 
155
 
int32_t Vio::keepalive(bool set_keep_alive)
 
123
static int32_t _vio_keepalive(Vio* vio, bool set_keep_alive)
156
124
{
157
125
  int r= 0;
158
126
  uint32_t opt= 0;
160
128
  if (set_keep_alive)
161
129
    opt= 1;
162
130
 
163
 
  r= setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
 
131
  r= setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
164
132
  if (r != 0)
165
133
  {
166
134
    perror("setsockopt");
170
138
  return r;
171
139
}
172
140
 
173
 
bool Vio::should_retry() const
 
141
static bool _vio_should_retry(Vio * vio)
174
142
{
 
143
  (void)vio;
175
144
  int en = errno;
176
145
  return (en == EAGAIN || en == EINTR ||
177
 
          en == EWOULDBLOCK);
 
146
          en == EWOULDBLOCK);
178
147
}
179
148
 
180
 
bool Vio::was_interrupted() const
 
149
static bool _vio_was_interrupted(Vio *vio)
181
150
{
 
151
  (void)vio;
182
152
  int en= errno;
183
153
  return (en == EAGAIN || en == EINTR ||
184
 
          en == EWOULDBLOCK || en == ETIMEDOUT);
185
 
}
186
 
 
187
 
bool Vio::peer_addr(char *buf, uint16_t *port, size_t buflen) const
 
154
          en == EWOULDBLOCK || en == ETIMEDOUT);
 
155
}
 
156
 
 
157
static int _vio_close(Vio * vio)
 
158
{
 
159
  int r=0;
 
160
 if (!vio->closed)
 
161
  {
 
162
    assert(vio->sd >= 0);
 
163
    if (shutdown(vio->sd, SHUT_RDWR))
 
164
      r= -1;
 
165
    if (close(vio->sd))
 
166
      r= -1;
 
167
  }
 
168
  vio->closed= true;
 
169
  vio->sd=   -1;
 
170
 
 
171
  return r;
 
172
}
 
173
 
 
174
static bool _vio_peer_addr(Vio *vio, char *buf, uint16_t *port, size_t buflen)
188
175
{
189
176
  int error;
190
177
  char port_buf[NI_MAXSERV];
191
 
  socklen_t al = sizeof(remote);
 
178
  socklen_t addrLen = sizeof(vio->remote);
192
179
 
193
 
  if (getpeername(sd, (struct sockaddr *) (&remote),
194
 
                  &al) != 0)
 
180
  if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote),
 
181
                  &addrLen) != 0)
195
182
  {
196
183
    return true;
197
184
  }
 
185
  vio->addrLen= (int)addrLen;
198
186
 
199
 
  if ((error= getnameinfo((struct sockaddr *)(&remote),
200
 
                          al,
 
187
  if ((error= getnameinfo((struct sockaddr *)(&vio->remote),
 
188
                          addrLen,
201
189
                          buf, buflen,
202
190
                          port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV)))
203
191
  {
209
197
  return false;
210
198
}
211
199
 
212
 
void Vio::timeout(bool is_sndtimeo, int32_t t)
 
200
static void _vio_timeout(Vio *vio, bool is_sndtimeo, int32_t timeout)
213
201
{
214
202
  int error;
215
203
 
216
204
  /* POSIX specifies time as struct timeval. */
217
205
  struct timeval wait_timeout;
218
 
  wait_timeout.tv_sec= t;
 
206
  wait_timeout.tv_sec= timeout;
219
207
  wait_timeout.tv_usec= 0;
220
208
 
221
 
  assert(t >= 0 && t <= INT32_MAX);
222
 
  assert(sd != -1);
223
 
  error= setsockopt(sd, SOL_SOCKET, is_sndtimeo ? SO_SNDTIMEO : SO_RCVTIMEO,
 
209
  assert(timeout >= 0 && timeout <= INT32_MAX);
 
210
  assert(vio->sd != -1);
 
211
  error= setsockopt(vio->sd, SOL_SOCKET, is_sndtimeo ? SO_SNDTIMEO : SO_RCVTIMEO,
224
212
                    &wait_timeout,
225
213
                    (socklen_t)sizeof(struct timeval));
226
214
  if (error == -1 && errno != ENOPROTOOPT)
230
218
  }
231
219
}
232
220
 
233
 
int Vio::get_errno() const
234
 
{
235
 
  return errno;
236
 
}
237
 
 
238
 
int Vio::get_fd() const
239
 
{
240
 
  return sd;
241
 
}
242
 
 
243
 
 
244
 
char *Vio::get_read_pos() const
245
 
{
246
 
  return read_pos;
247
 
}
248
 
 
249
 
char *Vio::get_read_end() const
250
 
{
251
 
  return read_end;
252
 
}
253
 
 
254
 
} /* namespace drizzle_plugin */
 
221
/* Open the socket or TCP/IP connection and read the fnctl() status */
 
222
Vio *mysql_protocol_vio_new(int sd)
 
223
{
 
224
  Vio *vio = (Vio*) malloc(sizeof(Vio));
 
225
  if (vio == NULL)
 
226
    return NULL;
 
227
 
 
228
  memset(vio, 0, sizeof(*vio));
 
229
  vio->closed= false;
 
230
  vio->sd= sd;
 
231
  vio->viodelete= _vio_delete;
 
232
  vio->vioerrno= _vio_errno;
 
233
  vio->read= _vio_read;
 
234
  vio->write= _vio_write;
 
235
  vio->fastsend= _vio_fastsend;
 
236
  vio->viokeepalive= _vio_keepalive;
 
237
  vio->should_retry= _vio_should_retry;
 
238
  vio->was_interrupted= _vio_was_interrupted;
 
239
  vio->vioclose= _vio_close;
 
240
  vio->peer_addr= _vio_peer_addr;
 
241
  vio->vioblocking= _vio_blocking;
 
242
  vio->timeout= _vio_timeout;
 
243
 
 
244
  /*
 
245
    We call fcntl() to set the flags and then immediately read them back
 
246
    to make sure that we and the system are in agreement on the state of
 
247
    things.
 
248
 
 
249
    An example of why we need to do this is FreeBSD (and apparently some
 
250
    other BSD-derived systems, like Mac OS X), where the system sometimes
 
251
    reports that the socket is set for non-blocking when it really will
 
252
    block.
 
253
  */
 
254
  fcntl(sd, F_SETFL, 0);
 
255
  vio->fcntl_mode= fcntl(sd, F_GETFL);
 
256
 
 
257
  return vio;
 
258
}