+namespace {
+ memcached_return_t send_quit_message(memcached_instance_st* instance)
+ {
+ memcached_return_t rc;
+ if (instance->root->flags.binary_protocol)
+ {
+ protocol_binary_request_quit request= {}; // = {.bytes= {0}};
+
+ initialize_binary_request(instance, request.message.header);
+
+ request.message.header.request.opcode = PROTOCOL_BINARY_CMD_QUIT;
+ request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
+
+ libmemcached_io_vector_st vector[]=
+ {
+ { request.bytes, sizeof(request.bytes) }
+ };
+
+ rc= memcached_vdo(instance, vector, 1, true);
+ }
+ else
+ {
+ libmemcached_io_vector_st vector[]=
+ {
+ { memcached_literal_param("quit\r\n") }
+ };
+
+ rc= memcached_vdo(instance, vector, 1, true);
+ }
+
+ return rc;
+ }
+
+ void drain_instance(memcached_instance_st* instance)
+ {
+ /* read until socket is closed, or there is an error
+ * closing the socket before all data is read
+ * results in server throwing away all data which is
+ * not read
+ *
+ * In .40 we began to only do this if we had been doing buffered
+ * requests of had replication enabled.
+ */
+ if (instance->root->flags.buffer_requests or instance->root->number_of_replicas)
+ {
+ memcached_io_slurp(instance);
+ }
+
+ /*
+ * memcached_io_read may call memcached_quit_server with io_death if
+ * it encounters problems, but we don't care about those occurences.
+ * The intention of that loop is to drain the data sent from the
+ * server to ensure that the server processed all of the data we
+ * sent to the server.
+ */
+ instance->server_failure_counter= 0;
+ instance->server_timeout_counter= 0;
+ }
+}
+