Abstraction (which will save us merge hell with 1.2).
[awesomized/libmemcached] / libmemcached / quit.cc
index b44b508e27ea00eacd3e6738d417a9a319902208..61930beb8c255af18596cae2cde2ec5d2d4f7e86 100644 (file)
 
 #include <libmemcached/common.h>
 
+namespace {
+  memcached_return_t send_quit_message(org::libmemcached::Instance* 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(org::libmemcached::Instance* 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;
+  }
+}
+
 /*
   This closes all connections (forces flush of input as well).
 
   will force data to be completed.
 */
 
-void memcached_quit_server(memcached_server_st *ptr, bool io_death)
+void memcached_quit_server(org::libmemcached::Instance* instance, bool io_death)
 {
-  if (ptr->fd != INVALID_SOCKET)
+  if (instance->valid())
   {
-    if (io_death == false && ptr->type != MEMCACHED_CONNECTION_UDP && ptr->options.is_shutting_down == false)
+    if (io_death == false and memcached_is_udp(instance->root) == false and instance->is_shutting_down() == false)
     {
-      memcached_return_t rc;
-      char buffer[MEMCACHED_MAX_BUFFER];
-
-      ptr->options.is_shutting_down= true;
+      send_quit_message(instance);
 
-      if (ptr->root->flags.binary_protocol)
-      {
-        protocol_binary_request_quit request= {}; // = {.bytes= {0}};
-        request.message.header.request.magic = PROTOCOL_BINARY_REQ;
-        request.message.header.request.opcode = PROTOCOL_BINARY_CMD_QUIT;
-        request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
-        rc= memcached_do(ptr, request.bytes, sizeof(request.bytes), true);
-      }
-      else
-      {
-        rc= memcached_do(ptr, memcached_literal_param("quit\r\n"), true);
-      }
-
-      WATCHPOINT_ASSERT(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_FETCH_NOTFINISHED);
-      (void)rc; // Shut up ICC
-
-      /* 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 (ptr->root->flags.buffer_requests || ptr->root->number_of_replicas)
-      {
-        ssize_t nread;
-        while (memcached_io_read(ptr, buffer, sizeof(buffer)/sizeof(*buffer),
-                                 &nread) == MEMCACHED_SUCCESS) {} ;
-      }
-
-
-      /*
-       * 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.
-       */
-      ptr->server_failure_counter= 0;
+      instance->start_close_socket();
+      drain_instance(instance);
     }
-    memcached_io_close(ptr);
   }
 
-  ptr->io_bytes_sent= 0;
-  ptr->write_buffer_offset= (size_t) ((ptr->type == MEMCACHED_CONNECTION_UDP) ? UDP_DATAGRAM_HEADER_LENGTH : 0);
-  ptr->read_buffer_length= 0;
-  ptr->read_ptr= ptr->read_buffer;
-  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;
+  instance->close_socket();
 
   if (io_death)
   {
-    ptr->server_failure_counter++;
-    set_last_disconnected_host(ptr);
+    memcached_mark_server_for_timeout(instance);
   }
 }
 
-void send_quit(memcached_st *ptr)
+void send_quit(Memcached *memc)
 {
-  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
+  for (uint32_t x= 0; x < memcached_server_count(memc); x++)
   {
-    memcached_server_write_instance_st instance=
-      memcached_server_instance_fetch(ptr, x);
+    org::libmemcached::Instance* instance= memcached_instance_fetch(memc, x);
 
     memcached_quit_server(instance, false);
   }
 }
 
-void memcached_quit(memcached_st *ptr)
+void memcached_quit(memcached_st *shell)
 {
-  if (initialize_query(ptr) != MEMCACHED_SUCCESS)
+  Memcached* memc= memcached2Memcached(shell);
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(memc, true)))
   {
     return;
   }
 
-  send_quit(ptr);
+  send_quit(memc);
 }