Skip to content

Commit 672ab98

Browse files
committed
INTERNAL: Refactor textual_value_fetch logic
1 parent 1f8f120 commit 672ab98

File tree

1 file changed

+60
-91
lines changed

1 file changed

+60
-91
lines changed

libmemcached/response.cc

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

57+
static memcached_return_t tokenize(char *str_ptr, char *end_ptr,
58+
char **tokens, size_t *ntokens)
59+
{
60+
size_t i;
61+
char *cur_ptr;
62+
for (i= 0; i < *ntokens; i++)
63+
{
64+
cur_ptr= str_ptr;
65+
while (!iscntrl(*cur_ptr) && !isspace(*cur_ptr))
66+
{
67+
if (cur_ptr >= end_ptr) return MEMCACHED_PARTIAL_READ;
68+
cur_ptr++;
69+
}
70+
if (cur_ptr == str_ptr) break;
71+
*cur_ptr= '\0';
72+
tokens[i]= str_ptr;
73+
str_ptr= cur_ptr + 1;
74+
}
75+
*ntokens= i;
76+
return MEMCACHED_SUCCESS;
77+
}
78+
5779
static memcached_return_t textual_value_fetch(memcached_server_write_instance_st ptr,
5880
char *buffer, size_t buffer_length,
5981
memcached_result_st *result)
6082
{
6183
char *string_ptr;
6284
char *end_ptr;
63-
char *next_ptr;
64-
size_t value_length;
65-
size_t to_read;
66-
ssize_t read_length= 0;
85+
ssize_t value_length;
86+
ssize_t read_length;
6787

6888
if (ptr->root->flags.use_udp)
6989
return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
7090

7191
WATCHPOINT_ASSERT(ptr->root);
92+
93+
string_ptr= buffer + 6; /* "VALUE " */
7294
end_ptr= buffer + buffer_length;
7395

7496
memcached_result_reset(result);
7597

76-
string_ptr= buffer;
77-
string_ptr+= 6; /* "VALUE " */
98+
char *tokens[4]= {NULL, };
99+
size_t ntoken= 4;
100+
101+
memcached_return_t rc= tokenize(string_ptr, end_ptr, tokens, &ntoken);
102+
if (rc != MEMCACHED_SUCCESS)
103+
return rc;
78104

79105
/* We load the key */
80106
{
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++;
107+
char *key= tokens[0] + memcached_array_size(ptr->root->_namespace);
108+
int key_length= snprintf(result->item_key, MEMCACHED_MAX_KEY, "%s", key);
109+
if (key_length < 0)
110+
{
111+
return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
92112
}
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;
113+
else if (key_length >= MEMCACHED_MAX_KEY)
114+
{
115+
snprintf(result->item_key + MEMCACHED_MAX_KEY - 4, 4, "...");
116+
key_length= MEMCACHED_MAX_KEY - 1;
100117
memcached_set_error(*ptr, MEMCACHED_KEY_TOO_BIG, MEMCACHED_AT);
101118
}
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);
114119

115-
if (end_ptr == string_ptr)
116-
goto read_error;
117-
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;
120+
result->key_length= (size_t)key_length;
134121
}
135-
else
122+
123+
result->item_flags= (uint32_t)strtoul(tokens[1], NULL, 10);
124+
value_length= (ssize_t)strtoull(tokens[2], NULL, 10);
125+
if (ntoken == 4)
136126
{
137-
string_ptr++;
138-
for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {};
139-
result->item_cas= strtoull(next_ptr, &string_ptr, 10);
127+
result->item_cas= strtoull(tokens[3], NULL, 10);
140128
}
141129

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

151136
{
152137
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))
138+
rc= memcached_io_read(ptr, value_ptr, value_length + 2, &read_length);
139+
if (rc == MEMCACHED_IN_PROGRESS)
163140
{
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;
141+
memcached_quit_server(ptr, true);
142+
return memcached_set_error(*ptr, rc, MEMCACHED_AT);
143+
}
144+
else if (memcached_failed(rc))
145+
{
146+
return rc;
169147
}
170-
}
171148

172-
if (read_length != (ssize_t)(value_length + 2))
173-
{
174-
goto read_error;
175-
}
149+
if (read_length != value_length + 2)
150+
{
151+
return MEMCACHED_PARTIAL_READ;
152+
}
176153

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;
154+
memset(value_ptr + value_length, 0, 2);
183155
memcached_string_set_length(&result->value, value_length);
184156
}
185157

186158
return MEMCACHED_SUCCESS;
187-
188-
read_error:
189-
return MEMCACHED_PARTIAL_READ;
190159
}
191160

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

0 commit comments

Comments
 (0)