~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/client.c

Added drizzleadmin.cc to POTFILES

Show diffs side-by-side

added added

removed removed

Lines of Context:
99
99
static void drizzle_close_free_options(DRIZZLE *drizzle);
100
100
static void drizzle_close_free(DRIZZLE *drizzle);
101
101
 
102
 
static int wait_for_data(int fd, int32_t timeout);
103
 
int connect_with_timeout(int fd, const struct sockaddr *name, uint namelen, int32_t timeout);
 
102
static int wait_for_data(my_socket fd, uint timeout);
104
103
 
105
104
CHARSET_INFO *default_client_charset_info = &my_charset_latin1;
106
105
 
109
108
char drizzle_server_last_error[DRIZZLE_ERRMSG_SIZE];
110
109
 
111
110
/****************************************************************************
112
 
  A modified version of connect().  connect_with_timeout() allows you to specify
 
111
  A modified version of connect().  my_connect() allows you to specify
113
112
  a timeout value, in seconds, that we should wait until we
114
113
  derermine we can't connect to a particular host.  If timeout is 0,
115
 
  connect_with_timeout() will behave exactly like connect().
 
114
  my_connect() will behave exactly like connect().
116
115
 
117
116
  Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
118
117
*****************************************************************************/
119
118
 
120
 
 
121
 
int connect_with_timeout(int fd, const struct sockaddr *name, uint namelen, int32_t timeout)
 
119
int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
 
120
         uint timeout)
122
121
{
123
122
  int flags, res, s_err;
124
123
 
145
144
  }
146
145
  if (res == 0)        /* Connected quickly! */
147
146
    return(0);
148
 
 
149
147
  return wait_for_data(fd, timeout);
150
148
}
151
149
 
157
155
  If not, we will use select()
158
156
*/
159
157
 
160
 
static int wait_for_data(int fd, int32_t timeout)
 
158
static int wait_for_data(my_socket fd, uint timeout)
161
159
{
 
160
#ifdef HAVE_POLL
162
161
  struct pollfd ufds;
163
162
  int res;
164
163
 
169
168
    errno= EINTR;
170
169
    return -1;
171
170
  }
172
 
  if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)) || (ufds.revents & POLLHUP))
 
171
  if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
173
172
    return -1;
174
173
  return 0;
 
174
#else
 
175
  SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
 
176
  fd_set sfds;
 
177
  struct timeval tv;
 
178
  time_t start_time, now_time;
 
179
  int res, s_err;
 
180
 
 
181
  if (fd >= FD_SETSIZE)        /* Check if wrong error */
 
182
    return 0;          /* Can't use timeout */
 
183
 
 
184
  /*
 
185
    Our connection is "in progress."  We can use the select() call to wait
 
186
    up to a specified period of time for the connection to suceed.
 
187
    If select() returns 0 (after waiting howevermany seconds), our socket
 
188
    never became writable (host is probably unreachable.)  Otherwise, if
 
189
    select() returns 1, then one of two conditions exist:
 
190
  
 
191
    1. An error occured.  We use getsockopt() to check for this.
 
192
    2. The connection was set up sucessfully: getsockopt() will
 
193
    return 0 as an error.
 
194
  
 
195
    Thanks goes to Andrew Gierth <andrew@erlenstar.demon.co.uk>
 
196
    who posted this method of timing out a connect() in
 
197
    comp.unix.programmer on August 15th, 1997.
 
198
  */
 
199
 
 
200
  FD_ZERO(&sfds);
 
201
  FD_SET(fd, &sfds);
 
202
  /*
 
203
    select could be interrupted by a signal, and if it is,
 
204
    the timeout should be adjusted and the select restarted
 
205
    to work around OSes that don't restart select and
 
206
    implementations of select that don't adjust tv upon
 
207
    failure to reflect the time remaining
 
208
   */
 
209
  start_time= my_time(0);
 
210
  for (;;)
 
211
  {
 
212
    tv.tv_sec = (long) timeout;
 
213
    tv.tv_usec = 0;
 
214
#if defined(HPUX10)
 
215
    if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0)
 
216
      break;
 
217
#else
 
218
    if ((res = select(fd+1, NULL, &sfds, NULL, &tv)) > 0)
 
219
      break;
 
220
#endif
 
221
    if (res == 0)          /* timeout */
 
222
      return -1;
 
223
    now_time= my_time(0);
 
224
    timeout-= (uint) (now_time - start_time);
 
225
    if (errno != EINTR || (int) timeout <= 0)
 
226
      return -1;
 
227
  }
 
228
 
 
229
  /*
 
230
    select() returned something more interesting than zero, let's
 
231
    see if we have any errors.  If the next two statements pass,
 
232
    we've got an open socket!
 
233
  */
 
234
 
 
235
  s_err=0;
 
236
  if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
 
237
    return(-1);
 
238
 
 
239
  if (s_err)
 
240
  {            /* getsockopt could succeed */
 
241
    errno = s_err;
 
242
    return(-1);          /* but return an error... */
 
243
  }
 
244
  return (0);          /* ok */
 
245
#endif /* HAVE_POLL */
175
246
}
176
247
 
177
248
 
1270
1341
 
1271
1342
    memset(&hints, 0, sizeof(hints));
1272
1343
    hints.ai_socktype= SOCK_STREAM;
1273
 
    /* OSX 10.5 was failing unless defined only as support IPV4 */
1274
 
#ifdef TARGET_OS_OSX
1275
 
    hints.ai_family= AF_INET;
1276
 
#endif
1277
 
 
 
1344
    hints.ai_protocol= IPPROTO_TCP;
 
1345
    hints.ai_family= AF_UNSPEC;
1278
1346
 
1279
1347
    snprintf(port_buf, NI_MAXSERV, "%d", port);
1280
1348
    gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst);
1290
1358
    /* We only look at the first item (something to think about changing in the future) */
1291
1359
    t_res= res_lst;
1292
1360
    {
1293
 
      int sock= socket(t_res->ai_family, t_res->ai_socktype,
 
1361
      my_socket sock= socket(t_res->ai_family, t_res->ai_socktype,
1294
1362
                             t_res->ai_protocol);
1295
1363
      if (sock == SOCKET_ERROR)
1296
1364
      {
1309
1377
        goto error;
1310
1378
      }
1311
1379
 
1312
 
      if (connect_with_timeout(sock, t_res->ai_addr, t_res->ai_addrlen, drizzle->options.connect_timeout))
 
1380
      if (my_connect(sock, t_res->ai_addr, t_res->ai_addrlen,
 
1381
                     drizzle->options.connect_timeout))
1313
1382
      {
1314
1383
        set_drizzle_extended_error(drizzle, CR_CONN_HOST_ERROR, unknown_sqlstate,
1315
1384
                                 ER(CR_CONN_HOST_ERROR), host, socket_errno);