예제 #1
0
void *
sock_timeout(void *arg)
{
    /* read nothing in this test case */
    (void)arg;
    struct sockaddr_in server_addr;
    char buf[32];
    struct timeval start, end, used;

    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(2000);
    int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    assert(sockfd > 0);
    CU_ASSERT(connect(sockfd, (struct sockaddr *)&server_addr, sizeof server_addr) == 0);
    crt_set_nonblock(sockfd);

    gettimeofday(&start, NULL);
    CU_ASSERT(crt_tcp_read_to(sockfd, buf, sizeof buf, 10) == -1);
    CU_ASSERT(crt_get_err_code() == EWOULDBLOCK);
    gettimeofday(&end, NULL);
    (&used)->tv_sec = (&end)->tv_sec - (&start)->tv_sec;
    (&used)->tv_usec = (&end)->tv_usec - (&start)->tv_usec;
    if ((&used)->tv_usec < 0){
        (&used)->tv_sec --;
        (&used)->tv_usec += 1000000;
    }
    CU_ASSERT(used.tv_sec == 0);
    CU_ASSERT(used.tv_usec <= 1000 * 20); /* more time to make sure: 20 ms */

    close(sockfd);

    crt_exit(NULL);
}
예제 #2
0
void *
sock_timeout2(void *arg)
{
    /*
     * read a bit of data in this test case
     *
     * the original intention is to test the following scenario:
     * 1. crt_tcp_read_to() read a few data from connection
     * 2. but it's timeout relative to it's argument
     *
     * if data was read, the standard activity should be:
     * 1. crt_tcp_read_to() return how many bytes have been read
     * 2. errno == 0
     *
     * if nothing was read, then:
     * 1. crt_tcp_read_to() return -1
     * 2. errno == EAGAIN or EWOULDBLOCK
     *
     * however, it's difficult to test the expected scenario due to it's hard
     * to control:
     * 1. crt_tcp_read_to() MUST be timeout
     * 2. data MUST be read
     *
     * it seems that if we send data as much as we can, it will be timeout
     */
    (void)arg;

    struct sockaddr_in server_addr;
    char buf[32];
    struct timeval start, end, used;

    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(2000);
    int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    assert(sockfd > 0);
    CU_ASSERT(connect(sockfd, (struct sockaddr *)&server_addr, sizeof server_addr) == 0);
    crt_set_nonblock(sockfd);

    gettimeofday(&start, NULL);
    /* set the timeout duration to the least length: 1ms */
    CU_ASSERT(crt_tcp_read_to(sockfd, buf, sizeof buf, 1) == 4);
    CU_ASSERT(crt_get_err_code() == 0);
    CU_ASSERT(strcmp(buf, "abc") == 0);
    gettimeofday(&end, NULL);
    (&used)->tv_sec = (&end)->tv_sec - (&start)->tv_sec;
    (&used)->tv_usec = (&end)->tv_usec - (&start)->tv_usec;
    if ((&used)->tv_usec < 0){
        (&used)->tv_sec --;
        (&used)->tv_usec += 1000000;
    }
    CU_ASSERT(used.tv_sec == 0);
    CU_ASSERT(used.tv_usec <= 1000 * 20); /* more time to make sure: 20 ms */

    close(sockfd);

    crt_exit(NULL);
}
예제 #3
0
static int
execute_one_slave(int slave_id, int arg_cnt, ...)
{
    va_list ap;
    int fd;
    char *request_stream;
    size_t request_len;
    int nread;

    fd = crt_tcp_timeout_connect(slave_ip(slave_id), slave_port(slave_id), MASTER_CONNECT_SLAVE_TIMEOUT);
    if (fd < 0)
    {
        if (crt_errno == ECONNREFUSED)
            return RET_CONNECT_REFUSED;
        else if (crt_errno == EWOULDBLOCK)
            return RET_CONNECT_TIMEOUT;
        else
            return RET_CONNECT_FAILED;
    }

    va_start(ap, arg_cnt);
    for (int i=0; i<arg_cnt; i++)
    {
        request_stream = va_arg(ap, char *);
        request_len = va_arg(ap, size_t);
        crt_tcp_write_to(fd, request_stream, request_len, MASTER_SEND_SLAVE_TIMEOUT);
    }
    va_end(ap);

    for ( ; ; )
    {
        nread = crt_tcp_read_to(fd, 

    return 0;
}

static struct query_response_s *
fetch_result(struct query_request_s *request_ptr)
{
    switch (request_ptr->cmd_type)
    {
    case cmd_sync:
    case cmd_power:
    case cmd_set:
    case cmd_delete:
        break;

    case cmd_get:
        break;

    default:
        break;
    }
    return NULL;
}

static int
sendback_result(int fd, struct query_response_s *response_ptr)
{
    return 0;
}

static void 
sendback_error_mesg(int fd)
{
    const char *error_mesg = MC_ERR_STR;
    crt_tcp_write_to(fd, (void*)error_mesg, strlen(error_mesg), g_master_settings.write_timeout);
}

static void *
handle_request(void *arg)
{
    int fd = (intptr_t)arg;
    ssize_t nread;
    struct query_request_s request;
    struct query_response_s *response_ptr;
    char *p;
    char remote_ip[IP_STR_LEN];
    struct sockaddr_in remote_peer;
    socklen_t addrlen;
    char warn_log_mesg[1024] = {0};
    int ret;
    pre_timer();

    launch_timer();
    crt_set_nonblock(fd);
    addrlen = sizeof remote_peer;
    getpeername(fd, (struct sockaddr *)&remote_peer, &addrlen);
    inet_ntop(AF_INET, &(remote_peer.sin_addr), remote_ip, sizeof remote_ip);
    memset(&request, 0, sizeof request);
    /* {{{ recv header */
    for (int i=0; i<MAX_RESP_HEADER_SIZE; i++)
    {
        nread = crt_tcp_read_to(fd, &request.query_head_buf[i], 1, g_master_settings.read_timeout);
        if (nread == 1)
        {
            if ((p=try_parse_memcached_string_head(&request)) == NULL)
                continue;
            else
                break;
        }
        else
        {
            ret = snprintf(warn_log_mesg, sizeof warn_log_mesg, "read sock failed: %d - %s", crt_errno, strerror(crt_errno));
            assert(ret < (int)sizeof warn_log_mesg); /* NOT <= */
            assert(ret >= 0);
            goto done;
        }
    }
    /* }}} */
    /* {{{ parse header & prepare for receiving data */
    request.query_head_buf_size = strlen(request.query_head_buf);
    if ((parse_memcached_string_head(&request) == RET_SUCCESS)
         && (request.parse_status == ps_succ))
    {
        switch (request.cmd_type)
        {
            case cmd_set:
                request.data_size += 2; /* alloc for tailing '\r\n' */
                request.data = slab_alloc(request.data_size);
                assert(request.data != NULL);
                nread = crt_tcp_read(fd, request.data, request.data_size);
                if (nread != (ssize_t)request.data_size)
                {
                    ret = snprintf(warn_log_mesg, sizeof warn_log_mesg,
                                   "read request body failed: nread = %zd, error = %d - %s",
                                   nread, crt_errno, strerror(crt_errno));
                    assert(ret < (int)sizeof warn_log_mesg); /* NOT <= */
                    assert(ret >= 0);
                    goto done;
                }
                break;

            case cmd_get:
            case cmd_delete:
                /* nothing to do */
                break;

            /* TODO */
            case cmd_sync:
            case cmd_power:
            default:
                break;
        }
    }
    else
    {
        sendback_error_mesg(fd);
        ret = snprintf(warn_log_mesg, sizeof warn_log_mesg, "parse request failed, cmd type: %d", request.cmd_type);
        assert(ret < (int)sizeof warn_log_mesg); /* NOT <= */
        assert(ret >= 0);
    }
    /* }}} */
    response_ptr = fetch_result(&request);
    sendback_result(fd, response_ptr);

done:
    if (request.data != NULL)
        slab_free(request.data);
    stop_timer();
    if (warn_log_mesg[0] == '\0')
    {
        log_notice("%s <Elapsed %ld.%06lds> {from: %s, fd = %d}", cmd_type_name(request.cmd_type), 
                   __used.tv_sec, __used.tv_usec, remote_ip, fd);
    }
    else
    {
        log_warn("%s <Elapsed %ld.%06lds> {from: %s, fd = %d} %s", cmd_type_name(request.cmd_type),
                 __used.tv_sec, __used.tv_usec, remote_ip, fd, warn_log_mesg);
    }
    close(fd);
    crt_exit(NULL);
}