waittime.tv_sec= 0;
waittime.tv_usec= ptr->root->snd_timeout;
- error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDTIMEO,
+ error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDTIMEO,
&waittime, (socklen_t)sizeof(struct timeval));
WATCHPOINT_ASSERT(error == 0);
}
waittime.tv_sec= 0;
waittime.tv_usec= ptr->root->rcv_timeout;
- error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVTIMEO,
+ error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVTIMEO,
&waittime, (socklen_t)sizeof(struct timeval));
WATCHPOINT_ASSERT(error == 0);
}
#endif
+ if (ptr->root->flags & MEM_NO_BLOCK)
{
int error;
struct linger linger;
- linger.l_onoff= 1;
- linger.l_linger= MEMCACHED_DEFAULT_TIMEOUT;
- error= setsockopt(ptr->fd, SOL_SOCKET, SO_LINGER,
+ linger.l_onoff= 1;
+ linger.l_linger= 0; /* By default on close() just drop the socket */
+ error= setsockopt(ptr->fd, SOL_SOCKET, SO_LINGER,
&linger, (socklen_t)sizeof(struct linger));
WATCHPOINT_ASSERT(error == 0);
}
int flag= 1;
int error;
- error= setsockopt(ptr->fd, IPPROTO_TCP, TCP_NODELAY,
+ error= setsockopt(ptr->fd, IPPROTO_TCP, TCP_NODELAY,
&flag, (socklen_t)sizeof(int));
WATCHPOINT_ASSERT(error == 0);
}
{
int error;
- error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDBUF,
+ error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDBUF,
&ptr->root->send_size, (socklen_t)sizeof(int));
WATCHPOINT_ASSERT(error == 0);
}
{
int error;
- error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVBUF,
+ error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVBUF,
&ptr->root->recv_size, (socklen_t)sizeof(int));
WATCHPOINT_ASSERT(error == 0);
}
- /* For the moment, not getting a nonblocking mode will not be fatal */
- if ((ptr->root->flags & MEM_NO_BLOCK) || ptr->root->connect_timeout)
- {
- int flags;
+ /* libmemcached will always use nonblocking IO to avoid write deadlocks */
+ int flags;
+ do
flags= fcntl(ptr->fd, F_GETFL, 0);
- unlikely (flags != -1)
- {
- (void)fcntl(ptr->fd, F_SETFL, flags | O_NONBLOCK);
- }
+ while (flags == -1 && (errno == EINTR || errno == EAGAIN));
+
+ unlikely (flags == -1)
+ return MEMCACHED_CONNECTION_FAILURE;
+ else if ((flags & O_NONBLOCK) == 0)
+ {
+ int rval;
+
+ do
+ rval= fcntl(ptr->fd, F_SETFL, flags | O_NONBLOCK);
+ while (rval == -1 && (errno == EINTR || errno == EAGAIN));
+
+ unlikely (rval == -1)
+ return MEMCACHED_CONNECTION_FAILURE;
}
return MEMCACHED_SUCCESS;
servAddr.sun_family= AF_UNIX;
strcpy(servAddr.sun_path, ptr->hostname); /* Copy filename */
- addrlen= strlen(servAddr.sun_path) + sizeof(servAddr.sun_family);
+ addrlen= (socklen_t) (strlen(servAddr.sun_path) + sizeof(servAddr.sun_family));
test_connect:
- if (connect(ptr->fd,
+ if (connect(ptr->fd,
(struct sockaddr *)&servAddr,
sizeof(servAddr)) < 0)
{
continue;
}
- if ((ptr->fd= socket(use->ai_family,
- use->ai_socktype,
+ if ((ptr->fd= socket(use->ai_family,
+ use->ai_socktype,
use->ai_protocol)) < 0)
{
ptr->cached_errno= errno;
(void)set_socket_options(ptr);
- int flags= 0;
- if (ptr->root->connect_timeout)
- {
- flags= fcntl(ptr->fd, F_GETFL, 0);
- if (flags != -1 && !(flags & O_NONBLOCK))
- (void)fcntl(ptr->fd, F_SETFL, flags | O_NONBLOCK);
- }
-
/* connect to server */
- while (ptr->fd != -1 &&
+ while (ptr->fd != -1 &&
connect(ptr->fd, use->ai_addr, use->ai_addrlen) < 0)
{
ptr->cached_errno= errno;
(void)close(ptr->fd);
ptr->fd= -1;
}
- }
+ }
else if (errno == EISCONN) /* we are connected :-) */
{
break;
- }
+ }
else if (errno != EINTR)
{
(void)close(ptr->fd);
ptr->fd= -1;
break;
- }
+ }
}
if (ptr->fd != -1)
{
- /* restore flags */
- if (ptr->root->connect_timeout && (ptr->root->flags & MEM_NO_BLOCK) == 0)
- (void)fcntl(ptr->fd, F_SETFL, flags & ~O_NONBLOCK);
-
WATCHPOINT_ASSERT(ptr->cursor_active == 0);
ptr->server_failure_counter= 0;
return MEMCACHED_SUCCESS;
if (gettimeofday(&next_time, NULL) == 0)
ptr->next_retry= next_time.tv_sec + ptr->root->retry_timeout;
}
- ptr->server_failure_counter+= 1;
+ ptr->server_failure_counter++;
if (ptr->cached_errno == 0)
return MEMCACHED_TIMEOUT;
+
return MEMCACHED_ERRNO; /* The last error should be from connect() */
}
LIBMEMCACHED_MEMCACHED_CONNECT_START();
/* both retry_timeout and server_failure_limit must be set in order to delay retrying a server on error. */
+ WATCHPOINT_ASSERT(ptr->root);
if (ptr->root->retry_timeout && ptr->root->server_failure_limit)
{
- struct timeval next_time;
+ struct timeval curr_time;
- gettimeofday(&next_time, NULL);
+ gettimeofday(&curr_time, NULL);
/* if we've had too many consecutive errors on this server, mark it dead. */
- if (ptr->server_failure_counter > ptr->root->server_failure_limit)
+ if (ptr->server_failure_counter >= ptr->root->server_failure_limit)
{
- ptr->next_retry= next_time.tv_sec + ptr->root->retry_timeout;
+ ptr->next_retry= curr_time.tv_sec + ptr->root->retry_timeout;
ptr->server_failure_counter= 0;
}
- if (next_time.tv_sec < ptr->next_retry)
+ if (curr_time.tv_sec < ptr->next_retry)
{
if (memcached_behavior_get(ptr->root, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS))
run_distribution(ptr->root);
+ ptr->root->last_disconnected_server = ptr;
return MEMCACHED_SERVER_MARKED_DEAD;
}
}
WATCHPOINT_ASSERT(0);
}
+ unlikely ( rc != MEMCACHED_SUCCESS) ptr->root->last_disconnected_server = ptr;
+
LIBMEMCACHED_MEMCACHED_CONNECT_END();
return rc;