Skip to content

Commit 5e6c677

Browse files
committed
INTERNAL: Refactor textual_value_fetch logic
1 parent 1f8f120 commit 5e6c677

File tree

1 file changed

+54
-94
lines changed

1 file changed

+54
-94
lines changed

libmemcached/response.cc

Lines changed: 54 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -54,94 +54,70 @@
5454
#include <libmemcached/common.h>
5555
#include <libmemcached/string.hpp>
5656

57+
static int tokenize(char *buffer, int length, char **tokens, int ntokens)
58+
{
59+
int i;
60+
int cur_str;
61+
int begin_str= 0;
62+
for (i= 0; i < ntokens; i++)
63+
{
64+
cur_str= begin_str;
65+
while (!iscntrl(buffer[cur_str]) && !isspace(buffer[cur_str]))
66+
{
67+
if (cur_str >= length) return -1;
68+
cur_str++;
69+
}
70+
if (cur_str == begin_str) break;
71+
buffer[cur_str]= '\0';
72+
tokens[i]= &buffer[begin_str];
73+
begin_str= cur_str + 1;
74+
}
75+
return i;
76+
}
77+
5778
static memcached_return_t textual_value_fetch(memcached_server_write_instance_st ptr,
5879
char *buffer, size_t buffer_length,
5980
memcached_result_st *result)
6081
{
6182
char *string_ptr;
62-
char *end_ptr;
63-
char *next_ptr;
64-
size_t value_length;
65-
size_t to_read;
66-
ssize_t read_length= 0;
83+
ssize_t value_length;
84+
ssize_t read_length;
6785

6886
if (ptr->root->flags.use_udp)
6987
return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
7088

7189
WATCHPOINT_ASSERT(ptr->root);
72-
end_ptr= buffer + buffer_length;
90+
91+
string_ptr= buffer + 6; /* "VALUE " */
7392

7493
memcached_result_reset(result);
7594

76-
string_ptr= buffer;
77-
string_ptr+= 6; /* "VALUE " */
95+
char *tokens[4]= {NULL, };
96+
int ntoken= tokenize(string_ptr, buffer_length - 6, tokens, 4);
97+
if (ntoken < 0)
98+
return MEMCACHED_PARTIAL_READ;
7899

79100
/* We load the key */
80101
{
81-
char *key= result->item_key;
82-
size_t key_length= 0;
83-
84-
string_ptr += memcached_array_size(ptr->root->_namespace); /* prefix length */
85-
86-
while (!iscntrl(*string_ptr) && !isspace(*string_ptr)) {
87-
if (key_length < MEMCACHED_MAX_KEY) {
88-
key[key_length]= *string_ptr;
89-
}
90-
key_length++;
91-
string_ptr++;
92-
}
93-
94-
if (key_length < MEMCACHED_MAX_KEY) {
95-
key[key_length]= 0;
96-
result->key_length= key_length;
97-
} else {
98-
snprintf(key + MEMCACHED_MAX_KEY - 4, 4, "...");
99-
result->key_length= MEMCACHED_MAX_KEY - 1;
102+
char *key= tokens[0] + memcached_array_size(ptr->root->_namespace);
103+
int key_length= snprintf(result->item_key, MEMCACHED_MAX_KEY, "%s", key);
104+
if (key_length >= MEMCACHED_MAX_KEY)
105+
{
106+
snprintf(result->item_key + MEMCACHED_MAX_KEY - 4, 4, "...");
107+
key_length= MEMCACHED_MAX_KEY - 1;
100108
memcached_set_error(*ptr, MEMCACHED_KEY_TOO_BIG, MEMCACHED_AT);
101109
}
102-
}
103-
104-
if (end_ptr == string_ptr)
105-
goto read_error;
106-
107-
/* Flags fetch move past space */
108-
string_ptr++;
109-
if (end_ptr == string_ptr)
110-
goto read_error;
111-
112-
for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {};
113-
result->item_flags= (uint32_t) strtoul(next_ptr, &string_ptr, 10);
114-
115-
if (end_ptr == string_ptr)
116-
goto read_error;
117110

118-
/* Length fetch move past space*/
119-
string_ptr++;
120-
if (end_ptr == string_ptr)
121-
goto read_error;
122-
123-
for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {};
124-
value_length= (size_t)strtoull(next_ptr, &string_ptr, 10);
125-
126-
if (end_ptr == string_ptr)
127-
goto read_error;
128-
129-
/* Skip spaces */
130-
if (*string_ptr == '\r')
131-
{
132-
/* Skip past the \r\n */
133-
string_ptr+= 2;
111+
result->key_length= (size_t)key_length;
134112
}
135-
else
113+
114+
result->item_flags= (uint32_t)strtoul(tokens[1], NULL, 10);
115+
value_length= (ssize_t)strtoull(tokens[2], NULL, 10);
116+
if (ntoken == 4)
136117
{
137-
string_ptr++;
138-
for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {};
139-
result->item_cas= strtoull(next_ptr, &string_ptr, 10);
118+
result->item_cas= strtoull(tokens[3], NULL, 10);
140119
}
141120

142-
if (end_ptr < string_ptr)
143-
goto read_error;
144-
145121
/* We add two bytes so that we can walk the \r\n */
146122
if (memcached_failed(memcached_string_check(&result->value, value_length +2)))
147123
{
@@ -150,43 +126,27 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
150126

151127
{
152128
char *value_ptr= memcached_string_value_mutable(&result->value);
153-
/*
154-
We read the \r\n into the string since not doing so is more
155-
cycles then the waster of memory to do so.
156-
157-
We are null terminating through, which will most likely make
158-
some people lazy about using the return length.
159-
*/
160-
to_read= (value_length) + 2;
161-
memcached_return_t rrc= memcached_io_read(ptr, value_ptr, to_read, &read_length);
162-
if (memcached_failed(rrc))
129+
memcached_return_t rc= memcached_io_read(ptr, value_ptr, value_length + 2, &read_length);
130+
if (rc == MEMCACHED_IN_PROGRESS)
163131
{
164-
if (rrc == MEMCACHED_IN_PROGRESS) {
165-
memcached_quit_server(ptr, true);
166-
return memcached_set_error(*ptr, rrc, MEMCACHED_AT);
167-
}
168-
return rrc;
132+
memcached_quit_server(ptr, true);
133+
return memcached_set_error(*ptr, rc, MEMCACHED_AT);
134+
}
135+
else if (memcached_failed(rc))
136+
{
137+
return rc;
169138
}
170-
}
171139

172-
if (read_length != (ssize_t)(value_length + 2))
173-
{
174-
goto read_error;
175-
}
140+
if (read_length != value_length + 2)
141+
{
142+
return MEMCACHED_PARTIAL_READ;
143+
}
176144

177-
/* This next bit blows the API, but this is internal....*/
178-
{
179-
char *char_ptr;
180-
char_ptr= memcached_string_value_mutable(&result->value);;
181-
char_ptr[value_length]= 0;
182-
char_ptr[value_length +1]= 0;
145+
memset(value_ptr + value_length, 0, 2);
183146
memcached_string_set_length(&result->value, value_length);
184147
}
185148

186149
return MEMCACHED_SUCCESS;
187-
188-
read_error:
189-
return MEMCACHED_PARTIAL_READ;
190150
}
191151

192152
static memcached_return_t textual_version_fetch(memcached_server_write_instance_st instance, char *buffer)

0 commit comments

Comments
 (0)