Incomming fixes from Charles on the replication branch.
[awesomized/libmemcached] / lib / memcached_auto.c
1 #include "common.h"
2
3 static memcached_return memcached_auto(memcached_st *ptr,
4 char *verb,
5 char *key, size_t key_length,
6 unsigned int offset,
7 uint64_t *value)
8 {
9 size_t send_length;
10 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
11 unsigned int server_key;
12 uint8_t replicas= 0;
13 memcached_return rc[MEMCACHED_MAX_REPLICAS];
14
15 unlikely (key_length == 0)
16 return MEMCACHED_NO_KEY_PROVIDED;
17
18 unlikely (ptr->hosts == NULL || ptr->number_of_hosts == 0)
19 return MEMCACHED_NO_SERVERS;
20
21 if ((ptr->flags & MEM_VERIFY_KEY) && (memcachd_key_test(&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
22 return MEMCACHED_BAD_KEY_PROVIDED;
23
24 server_key= memcached_generate_hash(ptr, key, key_length);
25
26 send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
27 "%s %.*s %u\r\n", verb,
28 (int)key_length, key,
29 offset);
30 unlikely (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
31 return MEMCACHED_WRITE_FAILURE;
32
33 do
34 {
35 rc[replicas]= memcached_do(&ptr->hosts[server_key], buffer, send_length, 1);
36 if (rc[replicas] != MEMCACHED_SUCCESS)
37 goto error;
38
39 rc[replicas]= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
40
41 /*
42 So why recheck responce? Because the protocol is brain dead :)
43 The number returned might end up equaling one of the string
44 values. Less chance of a mistake with strncmp() so we will
45 use it. We still called memcached_response() though since it
46 worked its magic for non-blocking IO.
47 */
48 if (!strncmp(buffer, "ERROR\r\n", 7))
49 {
50 *value= 0;
51 rc[replicas]= MEMCACHED_PROTOCOL_ERROR;
52 }
53 else if (!strncmp(buffer, "NOT_FOUND\r\n", 11))
54 {
55 *value= 0;
56 rc[replicas]= MEMCACHED_NOTFOUND;
57 }
58 else
59 {
60 *value= (uint64_t)strtoll(buffer, (char **)NULL, 10);
61 rc[replicas]= MEMCACHED_SUCCESS;
62 }
63 /* On error we just jump to the next potential server */
64 error:
65 if (ptr->number_of_replicas > 1)
66 {
67 if (server_key == (ptr->number_of_hosts - 1))
68 server_key= 0;
69 else
70 server_key++;
71 }
72 } while ((++replicas) < ptr->number_of_replicas);
73
74 /* As long as one object gets stored, we count this as a success */
75 while (replicas--)
76 {
77 if (rc[replicas] == MEMCACHED_STORED)
78 return MEMCACHED_SUCCESS;
79 }
80
81 return rc[0];
82 }
83
84 memcached_return memcached_increment(memcached_st *ptr,
85 char *key, size_t key_length,
86 uint32_t offset,
87 uint64_t *value)
88 {
89 memcached_return rc;
90
91 LIBMEMCACHED_MEMCACHED_INCREMENT_START();
92 rc= memcached_auto(ptr, "incr", key, key_length, offset, value);
93 LIBMEMCACHED_MEMCACHED_INCREMENT_END();
94
95 return rc;
96 }
97
98 memcached_return memcached_decrement(memcached_st *ptr,
99 char *key, size_t key_length,
100 uint32_t offset,
101 uint64_t *value)
102 {
103 memcached_return rc;
104
105 LIBMEMCACHED_MEMCACHED_DECREMENT_START();
106 rc= memcached_auto(ptr, "decr", key, key_length, offset, value);
107 LIBMEMCACHED_MEMCACHED_DECREMENT_END();
108
109 return rc;
110 }