Updates from Monty for Pandora
[awesomized/libmemcached] / example / memcached_light.c
index ff3e4044325b4f0d93e01bff8525cbd543975c6d..d88e5861a97a76c80a8455b0a72d2ffc061b060c 100644 (file)
  *                       the more "logical" interface.
  *   memcached_light.c - This file sets up all of the sockets and run the main
  *                       message loop.
+ *
+ *
+ * config.h is included so that I can use the ntohll/htonll on platforms that
+ * doesn't have that (this is a private function inside libmemcached, so you
+ * cannot use it directly from libmemcached without special modifications to
+ * the library)
  */
 
+#include "config.h"
 #include <assert.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <libmemcached/protocol_handler.h>
 #include <libmemcached/byteorder.h>
 #include "storage.h"
+#include "memcached_light.h"
 
-extern struct memcached_binary_protocol_callback_st interface_v0_impl;
-extern struct memcached_binary_protocol_callback_st interface_v1_impl;
+extern memcached_binary_protocol_callback_st interface_v0_impl;
+extern memcached_binary_protocol_callback_st interface_v1_impl;
 
 static int server_sockets[1024];
 static int num_server_sockets= 0;
 static void* socket_userdata_map[1024];
+static bool verbose= false;
+
+struct options_st {
+  char *pid_file;
+  bool has_port;
+  in_port_t port;
+} global_options;
+
+typedef struct options_st options_st;
 
 /**
  * Create a socket and bind it to a specific port number
  * @param port the port number to bind to
  */
-static int server_socket(const char *port) {
+static int server_socket(const char *port)
+{
   struct addrinfo *ai;
   struct addrinfo hints= { .ai_flags= AI_PASSIVE,
                            .ai_family= AF_UNSPEC,
@@ -82,12 +100,14 @@ static int server_socket(const char *port) {
     }
 
     if ((flags & O_NONBLOCK) != O_NONBLOCK)
+    {
       if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1)
       {
         perror("Failed to set socket to nonblocking mode");
         close(sock);
         continue;
       }
+    }
 
     flags= 1;
     if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags)) != 0)
@@ -153,25 +173,33 @@ static const char* comcode2str(uint8_t cmd)
 /**
  * Print out the command we are about to execute
  */
-static void pre_execute(const void *cookie, protocol_binary_request_header *header)
+static void pre_execute(const void *cookie __attribute__((unused)),
+                        protocol_binary_request_header *header __attribute__((unused)))
 {
-  const char *cmd= comcode2str(header->request.opcode);
-  if (cmd != NULL)
-    fprintf(stderr, "pre_execute from %p: %s\n", cookie, cmd);
-  else
-    fprintf(stderr, "pre_execute from %p: 0x%02x\n", cookie, header->request.opcode);
+  if (verbose)
+  {
+    const char *cmd= comcode2str(header->request.opcode);
+    if (cmd != NULL)
+      fprintf(stderr, "pre_execute from %p: %s\n", cookie, cmd);
+    else
+      fprintf(stderr, "pre_execute from %p: 0x%02x\n", cookie, header->request.opcode);
+  }
 }
 
 /**
  * Print out the command we just executed
  */
-static void post_execute(const void *cookie, protocol_binary_request_header *header)
+static void post_execute(const void *cookie __attribute__((unused)),
+                         protocol_binary_request_header *header __attribute__((unused)))
 {
-  const char *cmd= comcode2str(header->request.opcode);
-  if (cmd != NULL)
-    fprintf(stderr, "post_execute from %p: %s\n", cookie, cmd);
-  else
-    fprintf(stderr, "post_execute from %p: 0x%02x\n", cookie, header->request.opcode);
+  if (verbose)
+  {
+    const char *cmd= comcode2str(header->request.opcode);
+    if (cmd != NULL)
+      fprintf(stderr, "post_execute from %p: %s\n", cookie, cmd);
+    else
+      fprintf(stderr, "post_execute from %p: 0x%02x\n", cookie, header->request.opcode);
+  }
 }
 
 /**
@@ -207,30 +235,66 @@ static void work(void);
  */
 int main(int argc, char **argv)
 {
-  bool port_specified= false;
   int cmd;
-  struct memcached_binary_protocol_callback_st *interface= &interface_v0_impl;
+  memcached_binary_protocol_callback_st *interface= &interface_v0_impl;
+
+  memset(&global_options, 0, sizeof(global_options));
 
-  while ((cmd= getopt(argc, argv, "1p:?")) != EOF)
+  /*
+   * We need to initialize the handlers manually due to a bug in the
+   * warnings generated by struct initialization in gcc (all the way up to 4.4)
+   */
+  initialize_interface_v0_handler();
+
+  while ((cmd= getopt(argc, argv, "v1pP:?h")) != EOF)
   {
     switch (cmd) {
     case '1':
       interface= &interface_v1_impl;
       break;
+    case 'P':
+      global_options.pid_file= strdup(optarg);
+      break;
     case 'p':
-      port_specified= true;
+      global_options.has_port= true;
       (void)server_socket(optarg);
       break;
+    case 'v':
+      verbose= true;
+      break;
+    case 'h':  /* FALLTHROUGH */
     case '?':  /* FALLTHROUGH */
     default:
-      (void)fprintf(stderr, "Usage: %s [-p port]\n", argv[0]);
+      (void)fprintf(stderr, "Usage: %s [-p port] [-v] [-1]\n", argv[0]);
       return 1;
     }
   }
 
-  if (!port_specified)
+  if (! initialize_storage())
+  {
+    /* Error message already printed */
+    return 1;
+  }
+
+  if (! global_options.has_port)
     (void)server_socket("9999");
 
+  if (global_options.pid_file)
+  {
+    FILE *pid_file;
+    uint32_t pid;
+
+    pid_file= fopen(global_options.pid_file, "w+");
+    perror(strerror(errno));
+
+    if (pid_file == NULL)
+      abort();
+
+    pid= (uint32_t)getpid();
+    fprintf(pid_file, "%u\n", pid);
+    fclose(pid_file);
+  }
+
   if (num_server_sockets == 0)
   {
     fprintf(stderr, "I don't have any server sockets\n");
@@ -246,8 +310,8 @@ int main(int argc, char **argv)
   interface->post_execute= post_execute;
   interface->unknown= unknown;
 
-  struct memcached_binary_protocol_st *protocol_handle;
-  if ((protocol_handle= memcached_binary_protocol_create_instance()) == NULL)
+  struct memcached_protocol_st *protocol_handle;
+  if ((protocol_handle= memcached_protocol_create_instance()) == NULL)
   {
     fprintf(stderr, "Failed to allocate protocol handle\n");
     return 1;
@@ -266,7 +330,8 @@ int main(int argc, char **argv)
   return 0;
 }
 
-static void work(void) {
+static void work(void)
+{
 #define MAX_SERVERS_TO_POLL 100
   struct pollfd fds[MAX_SERVERS_TO_POLL];
   int max_poll;
@@ -276,7 +341,6 @@ static void work(void) {
     fds[max_poll].events= POLLIN;
     fds[max_poll].revents= 0;
     fds[max_poll].fd= server_sockets[max_poll];
-    ++max_poll;
   }
 
   while (true)
@@ -309,11 +373,11 @@ static void work(void) {
             continue;
           }
 
-          struct memcached_binary_protocol_st *protocol;
+          struct memcached_protocol_st *protocol;
           protocol= socket_userdata_map[fds[x].fd];
 
-          struct memcached_binary_protocol_client_st* c;
-          c= memcached_binary_protocol_create_client(protocol, sock);
+          struct memcached_protocol_client_st* c;
+          c= memcached_protocol_create_client(protocol, sock);
           if (c == NULL)
           {
             fprintf(stderr, "Failed to create client\n");
@@ -331,23 +395,22 @@ static void work(void) {
         else
         {
           /* drive the client */
-          struct memcached_binary_protocol_client_st* c;
+          struct memcached_protocol_client_st* c;
           c= socket_userdata_map[fds[x].fd];
           assert(c != NULL);
           fds[max_poll].events= 0;
 
-          switch (memcached_binary_protocol_client_work(c))
-          {
-          case WRITE_EVENT:
-          case READ_WRITE_EVENT:
+          memcached_protocol_event_t events= memcached_protocol_client_work(c);
+          if (events & MEMCACHED_PROTOCOL_WRITE_EVENT)
             fds[max_poll].events= POLLOUT;
-            /* FALLTHROUGH */
-          case READ_EVENT:
-            fds[max_poll].events |= POLLIN;
-            break;
-          case ERROR_EVENT:
-          default: /* ERROR or unknown state.. close */
-            memcached_binary_protocol_client_destroy(c);
+
+          if (events & MEMCACHED_PROTOCOL_READ_EVENT)
+            fds[max_poll].events= POLLIN;
+
+          if (!(events & MEMCACHED_PROTOCOL_PAUSE_EVENT ||
+                fds[max_poll].events != 0))
+          {
+            memcached_protocol_client_destroy(c);
             close(fds[x].fd);
             fds[x].events= 0;