コード例 #1
0
ファイル: as_event.c プロジェクト: XeCycle/aerospike-client-c
int
as_event_create_socket(as_event_command* cmd)
{
    // Create a non-blocking socket.
    int fd = as_socket_create_nb();

    if (fd < 0) {
        as_error err;
        as_error_set_message(&err, AEROSPIKE_ERR_ASYNC_CONNECTION, "Failed to create non-blocking socket");
        as_event_connect_error(cmd, &err, fd);
        return -1;
    }

    if (cmd->pipe_listener != NULL) {
        if (as_event_send_buffer_size) {
            if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &as_event_send_buffer_size, sizeof(as_event_send_buffer_size)) < 0) {
                as_error err;
                as_error_update(&err, AEROSPIKE_ERR_ASYNC_CONNECTION,
                                "Failed to configure pipeline send buffer. size %d error %d (%s)",
                                as_event_send_buffer_size, errno, strerror(errno));
                as_event_connect_error(cmd, &err, fd);
                return -1;
            }
        }

        if (as_event_recv_buffer_size) {
            if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &as_event_recv_buffer_size, sizeof(as_event_recv_buffer_size)) < 0) {
                as_error err;
                as_error_update(&err, AEROSPIKE_ERR_ASYNC_CONNECTION,
                                "Failed to configure pipeline receive buffer. size %d error %d (%s)",
                                as_event_recv_buffer_size, errno, strerror(errno));
                as_event_connect_error(cmd, &err, fd);
                return -1;
            }
        }

#if defined(__linux__)
        if (as_event_recv_buffer_size) {
            if (setsockopt(fd, SOL_TCP, TCP_WINDOW_CLAMP, &as_event_recv_buffer_size, sizeof(as_event_recv_buffer_size)) < 0) {
                as_error err;
                as_error_set_message(&err, AEROSPIKE_ERR_ASYNC_CONNECTION, "Failed to configure pipeline TCP window.");
                as_event_connect_error(cmd, &err, fd);
                return -1;
            }
        }
#endif

        int arg = 0;

        if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &arg, sizeof(arg)) < 0) {
            as_error err;
            as_error_set_message(&err, AEROSPIKE_ERR_ASYNC_CONNECTION, "Failed to configure pipeline Nagle algorithm.");
            as_event_connect_error(cmd, &err, fd);
            return -1;
        }
    }
    return fd;
}
コード例 #2
0
static void
as_uv_connect(as_event_command* cmd)
{
	int fd = as_event_create_socket(cmd);
	
	if (fd < 0) {
		return;
	}
	
	as_event_connection* conn = cmd->conn;
	uv_tcp_t* socket = &conn->socket;
	int status = uv_tcp_init(cmd->event_loop->loop, socket);
	
	if (status) {
		as_error err;
		as_error_update(&err, AEROSPIKE_ERR_ASYNC_CONNECTION, "uv_tcp_init failed: %s", uv_strerror(status));
		// Call standard event connection error handler because as_uv_connect_error() requires that
		// uv_tcp_init() has already succeeded.
		as_event_connect_error(cmd, &err, fd);
		return;
	}
	
	// Define externally created fd to uv_tcp_t.
	status = uv_tcp_open(socket, fd);
	
	if (status) {
		as_error err;
		as_error_update(&err, AEROSPIKE_ERR_ASYNC_CONNECTION, "uv_tcp_open failed: %s", uv_strerror(status));
		// Close fd directly because we created it outside of libuv and uv_tcp_t does not know about it here.
		close(fd);
		as_uv_connect_error(cmd, &err);
		return;
	}
	
	socket->data = conn;
	conn->req.connect.data = cmd;
	
	as_node* node = cmd->node;
	as_address* primary = as_vector_get(&node->addresses, node->address_index);
	
	status = uv_tcp_connect(&conn->req.connect, socket, (struct sockaddr*)&primary->addr, as_uv_connected);
	
	if (status) {
		as_error err;
		as_error_update(&err, AEROSPIKE_ERR_ASYNC_CONNECTION, "uv_tcp_connect failed: %s", uv_strerror(status));
		as_uv_connect_error(cmd, &err);
	}
}
コード例 #3
0
static void
as_ev_connect(as_event_command* cmd)
{
	int fd = as_event_create_socket(cmd);
	
	if (fd < 0) {
		return;
	}
		
	// Try primary address.
	as_node* node = cmd->node;
	as_address* primary = as_vector_get(&node->addresses, node->address_index);
	
	// Attempt non-blocking connection.
	if (connect(fd, (struct sockaddr*)&primary->addr, sizeof(struct sockaddr)) == 0) {
		as_ev_watcher_init(cmd, fd);
		return;
	}
	
	// Check if connection is in progress.
	if (errno == EINPROGRESS) {
		as_ev_watcher_init(cmd, fd);
		return;
	}
	
	// Try other addresses.
	as_vector* addresses = &node->addresses;
	for (uint32_t i = 0; i < addresses->size; i++) {
		as_address* address = as_vector_get(addresses, i);
		
		// Address points into alias array, so pointer comparison is sufficient.
		if (address != primary) {
			if (connect(fd, (struct sockaddr*)&address->addr, sizeof(struct sockaddr)) == 0) {
				// Replace invalid primary address with valid alias.
				// Other threads may not see this change immediately.
				// It's just a hint, not a requirement to try this new address first.
				as_log_debug("Change node address %s %s:%d", node->name, address->name, (int)cf_swap_from_be16(address->addr.sin_port));
				ck_pr_store_32(&node->address_index, i);
				as_ev_watcher_init(cmd, fd);
				return;
			}
			
			// Check if connection is in progress.
			if (errno == EINPROGRESS) {
				// Replace invalid primary address with valid alias.
				// Other threads may not see this change immediately.
				// It's just a hint, not a requirement to try this new address first.
				as_log_debug("Change node address %s %s:%d", node->name, address->name, (int)cf_swap_from_be16(address->addr.sin_port));
				ck_pr_store_32(&node->address_index, i);
				
				// Connection hasn't finished.
				as_ev_watcher_init(cmd, fd);
				return;
			}
		}
	}
	
	// Failed to start a connection on any socket address.
	as_error err;
	as_error_update(&err, AEROSPIKE_ERR_ASYNC_CONNECTION, "Failed to connect: %s %s:%d",
					node->name, primary->name, (int)cf_swap_from_be16(primary->addr.sin_port));
	as_event_connect_error(cmd, &err, fd);
}