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;
}