static apr_status_t plus_minus()

in redis/apr_redis.c [1233:1362]


static apr_status_t plus_minus(apr_redis_t *rc,
                    int incr,
                    const char *key,
                    apr_int32_t inc,
                    apr_uint32_t *new_value)
{
    apr_status_t rv;
    apr_redis_server_t *rs;
    apr_redis_conn_t *conn;
    apr_uint32_t hash;
    apr_size_t written;
    apr_size_t len, klen;
    struct iovec vec[12];
    char keysize_str[LILBUFF_SIZE];
    char inc_str[LILBUFF_SIZE];
    char inc_str_len[LILBUFF_SIZE];
    int i = 0;

    klen = strlen(key);
    hash = apr_redis_hash(rc, key, klen);
    rs = apr_redis_find_server_hash(rc, hash);
    if (rs == NULL)
        return APR_NOTFOUND;

    rv = rs_find_conn(rs, &conn);

    if (rv != APR_SUCCESS) {
        apr_redis_disable_server(rc, rs);
        return rv;
    }

    /*
     * RESP Command:
     *   *2|*3
     *   $4|$6
     *   INCR/DECR|INCRBY/DECRBY
     *   $<keylen>
     *   key
     *   <:inc>
     */
    if (inc == 1) {
        vec[i].iov_base = RC_RESP_2;
        vec[i].iov_len = RC_RESP_2_LEN;
        i++;

        vec[i].iov_base = "$4\r\n";
        vec[i].iov_len = sizeof("$4\r\n")-1;
        i++;

        if (incr)
            vec[i].iov_base = "INCR\r\n";
        else
            vec[i].iov_base = "DECR\r\n";
        vec[i].iov_len = sizeof("INCR\r\n")-1;
        i++;
    }
    else {
        vec[i].iov_base = RC_RESP_3;
        vec[i].iov_len = RC_RESP_3_LEN;
        i++;

        vec[i].iov_base = "$6\r\n";
        vec[i].iov_len = sizeof("$6\r\n")-1;
        i++;

       if (incr)
            vec[i].iov_base = "INCRBY\r\n";
        else
            vec[i].iov_base = "DECRBY\r\n";
        vec[i].iov_len = sizeof("INCRBY\r\n")-1;
        i++;
    }

    len = apr_snprintf(keysize_str, LILBUFF_SIZE, "$%" APR_SIZE_T_FMT "\r\n",
                     klen);
    vec[i].iov_base = keysize_str;
    vec[i].iov_len = len;
    i++;

    vec[i].iov_base = (void *) key;
    vec[i].iov_len = klen;
    i++;

    vec[i].iov_base = RC_EOL;
    vec[i].iov_len = RC_EOL_LEN;
    i++;

    if (inc != 1) {
        len = apr_snprintf(inc_str, LILBUFF_SIZE, "%d\r\n", inc);
        klen = apr_snprintf(inc_str_len, LILBUFF_SIZE, "$%d\r\n", (int)(len-2));
        vec[i].iov_base = inc_str_len;
        vec[i].iov_len = klen;
        i++;

        vec[i].iov_base = inc_str;
        vec[i].iov_len = len;
        i++;

        vec[i].iov_base = RC_EOL;
        vec[i].iov_len = RC_EOL_LEN;
        i++;
    }

    rv = apr_socket_sendv(conn->sock, vec, i, &written);

    if (rv != APR_SUCCESS) {
        rs_bad_conn(rs, conn);
        apr_redis_disable_server(rc, rs);
        return rv;
    }

    rv = get_server_line(conn);
    if (rv != APR_SUCCESS) {
        rs_bad_conn(rs, conn);
        apr_redis_disable_server(rc, rs);
        return rv;
    }
    if (strncmp(RS_NOT_FOUND_GET, conn->buffer, RS_NOT_FOUND_GET_LEN) == 0) {
        rv = APR_NOTFOUND;
    }
    else if (*conn->buffer == ':') {
        *new_value = atoi((const char *)(conn->buffer + 1));
        rv = APR_SUCCESS;
    }
    else {
        rv = APR_EGENERAL;
    }
    rs_release_conn(rs, conn);
    return rv;
}