+ size_t x;
+ char *buffer_ptr;
+
+ buffer_ptr= buffer;
+
+ for (x= 0, buffer_ptr= buffer;
+ x < length; x++)
+ {
+ if (!ptr->read_buffer_length)
+ {
+ if (length > 1)
+ {
+
+ size_t data_read;
+ data_read= recv(ptr->hosts[server_key].fd,
+ buffer_ptr,
+ length - x, 0);
+ if (data_read == -1)
+ {
+ return -1;
+ }
+ if (data_read == 0)
+ return x;
+
+ data_read+= x;
+
+ return data_read;
+ }
+ else
+ {
+ size_t data_read;
+try_again:
+
+ if (ptr->flags & MEM_NO_BLOCK)
+ {
+ struct timeval local_tv;
+ fd_set set;
+
+ memset(&local_tv, 0, sizeof(struct timeval));
+
+ local_tv.tv_sec= 0;
+ local_tv.tv_usec= 300;
+
+ FD_ZERO(&set);
+ FD_SET(ptr->hosts[server_key].fd, &set);
+
+ select(1, &set, NULL, NULL, &local_tv);
+ }
+
+ data_read= recv(ptr->hosts[server_key].fd,
+ ptr->read_buffer,
+ MEMCACHED_MAX_BUFFER, 0);
+ if (data_read == -1)
+ {
+ if (errno == EAGAIN)
+ goto try_again;
+ return -1;
+ }
+ ptr->read_buffer_length= data_read;
+ ptr->read_ptr= ptr->read_buffer;
+ }
+
+ if (ptr->read_buffer_length == -1)
+ return -1;
+ if (ptr->read_buffer_length == 0)
+ return x;
+ }
+ *buffer_ptr= *ptr->read_ptr;
+ buffer_ptr++;
+ ptr->read_ptr++;
+ ptr->read_buffer_length--;
+ }
+
+ return length;