Also fixed regression test so that we check for invalid argment return.
ptr->options.is_shutting_down= false;
memcached_server_response_reset(ptr);
+ // We reset the version so that if we end up talking to a different server
+ // we don't have stale server version information.
+ ptr->major_version= ptr->minor_version= ptr->micro_version= UINT8_MAX;
+
if (io_death)
{
ptr->server_failure_counter++;
self->state.is_dead= false;
WATCHPOINT_SET(self->io_wait_count.read= 0);
WATCHPOINT_SET(self->io_wait_count.write= 0);
- self->major_version= 0;
- self->micro_version= 0;
- self->minor_version= 0;
+ self->major_version= UINT8_MAX;
+ self->micro_version= UINT8_MAX;
+ self->minor_version= UINT8_MAX;
self->type= type;
self->read_ptr= self->read_buffer;
self->cached_server_error= NULL;
uint32_t read;
uint32_t write;
} io_wait_count;
- uint8_t major_version;
- uint8_t micro_version;
- uint8_t minor_version;
+ uint8_t major_version; // Default definition of UINT8_MAX means that it has not been set.
+ uint8_t micro_version; // ditto
+ uint8_t minor_version; // ditto
memcached_connection_t type;
char *read_ptr;
char *cached_server_error;
memcached_server_write_instance_st instance=
memcached_server_instance_fetch(ptr, x);
+ // Optimization, we only fetch version once.
+ if (instance->major_version != UINT8_MAX)
+ continue;
+
rrc= memcached_do(instance, command, send_length, true);
if (rrc != MEMCACHED_SUCCESS)
{
- instance->major_version= instance->minor_version= instance->micro_version= 0;
+ instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
rrc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
if (rrc != MEMCACHED_SUCCESS)
{
- instance->major_version= instance->minor_version= instance->micro_version= 0;
+ instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
instance->major_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
if (errno == ERANGE)
{
- instance->major_version= instance->minor_version= instance->micro_version= 0;
+ instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
instance->minor_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
if (errno == ERANGE)
{
- instance->major_version= instance->minor_version= instance->micro_version= 0;
+ instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
instance->micro_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
if (errno == ERANGE)
{
- instance->major_version= instance->minor_version= instance->micro_version= 0;
+ instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
rc= MEMCACHED_SOME_ERRORS;
continue;
}
memcached_server_write_instance_st instance=
memcached_server_instance_fetch(ptr, x);
+ if (instance->major_version != UINT8_MAX)
+ continue;
+
rrc= memcached_do(instance, request.bytes, sizeof(request.bytes), true);
if (rrc != MEMCACHED_SUCCESS)
{
memcached_server_write_instance_st instance=
memcached_server_instance_fetch(ptr, x);
+ if (instance->major_version != UINT8_MAX)
+ continue;
+
if (memcached_server_response_count(instance) > 0)
{
memcached_return_t rrc;
}
instance->major_version= (uint8_t)strtol(buffer, &p, 10);
+ if (errno == ERANGE)
+ {
+ instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
+ rc= MEMCACHED_SOME_ERRORS;
+ continue;
+ }
+
instance->minor_version= (uint8_t)strtol(p + 1, &p, 10);
+ if (errno == ERANGE)
+ {
+ instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
+ rc= MEMCACHED_SOME_ERRORS;
+ continue;
+ }
+
instance->micro_version= (uint8_t)strtol(p + 1, NULL, 10);
+ if (errno == ERANGE)
+ {
+ instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
+ rc= MEMCACHED_SOME_ERRORS;
+ continue;
+ }
+
}
}
// if (! if_successful)
{
fprintf(stderr, "\n----------------------------------------------------------------------\n");
- fprintf(stderr, "\nDumping Server Information\n");
+ fprintf(stderr, "\nDumping Server Information\n\n");
memcached_server_fn callbacks[1];
- memcached_version(memc);
-
- memcached_version(memc);
callbacks[0]= dump_server_information;
memcached_server_cursor(memc, callbacks, (void *)stderr, 1);
memcached_return_t rc= memcached_delete(memc, "foo", 3, 1);
/* but there is a bug in some of the memcached servers (1.4) that treats
- * the counter as noreply so it doesn't send the proper error message
- */
- test_true(rc == MEMCACHED_PROTOCOL_ERROR || rc == MEMCACHED_NOTFOUND || rc == MEMCACHED_CLIENT_ERROR);
+ * the counter as noreply so it doesn't send the proper error message
+ */
+ test_true_got(rc == MEMCACHED_PROTOCOL_ERROR || rc == MEMCACHED_NOTFOUND || rc == MEMCACHED_CLIENT_ERROR || rc == MEMCACHED_INVALID_ARGUMENTS, memcached_strerror(NULL, rc));
/* And buffered mode should be disabled and we should get protocol error */
test_true(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1) == MEMCACHED_SUCCESS);
rc= memcached_delete(memc, "foo", 3, 1);
- test_true(rc == MEMCACHED_PROTOCOL_ERROR || rc == MEMCACHED_NOTFOUND || rc == MEMCACHED_CLIENT_ERROR);
+ test_true_got(rc == MEMCACHED_PROTOCOL_ERROR || rc == MEMCACHED_NOTFOUND || rc == MEMCACHED_CLIENT_ERROR || rc == MEMCACHED_INVALID_ARGUMENTS, memcached_strerror(NULL, rc));
/* Same goes for noreply... */
test_true(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 1) == MEMCACHED_SUCCESS);
rc= memcached_delete(memc, "foo", 3, 1);
- test_true(rc == MEMCACHED_PROTOCOL_ERROR || rc == MEMCACHED_NOTFOUND || rc == MEMCACHED_CLIENT_ERROR);
+ test_true_got(rc == MEMCACHED_PROTOCOL_ERROR || rc == MEMCACHED_NOTFOUND || rc == MEMCACHED_CLIENT_ERROR || rc == MEMCACHED_INVALID_ARGUMENTS, memcached_strerror(NULL, rc));
/* but a normal request should go through (and be buffered) */
test_true((rc= memcached_delete(memc, "foo", 3, 0)) == MEMCACHED_BUFFERED);
do \
{ \
if (1) { \
- fprintf(stderr, "\nFailed in %s:%d: %s\n", __FILE__, __LINE__, #A);\
+ fprintf(stderr, "\nFailed at %s:%d: %s\n", __FILE__, __LINE__, #A);\
create_core(); \
return TEST_FAILURE; \
} \
do \
{ \
if (! (A)) { \
- fprintf(stderr, "\nAssertion failed in %s:%d: %s\n", __FILE__, __LINE__, #A);\
+ fprintf(stderr, "\nAssertion failed at %s:%d: %s\n", __FILE__, __LINE__, #A);\
+ create_core(); \
+ return TEST_FAILURE; \
+ } \
+} while (0)
+
+#define test_true_got(A,B) \
+do \
+{ \
+ if (! (A)) { \
+ fprintf(stderr, "\nAssertion failed at %s:%d: \"%s\" received \"%s\"\n", __FILE__, __LINE__, #A, (B));\
create_core(); \
return TEST_FAILURE; \
} \
do \
{ \
if ((A)) { \
- fprintf(stderr, "\nAssertion failed in %s:%d: %s\n", __FILE__, __LINE__, #A);\
+ fprintf(stderr, "\nAssertion failed at %s:%d: %s\n", __FILE__, __LINE__, #A);\
create_core(); \
return TEST_FAILURE; \
} \