Updates from Monty for Pandora
[awesomized/libmemcached] / example / memcached_light.c
index 4343b835e265b9e5ca4a85bc5fff86414990dd1a..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,
@@ -218,23 +235,34 @@ 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, "v1p:?")) != 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] [-v] [-1]\n", argv[0]);
@@ -242,15 +270,31 @@ int main(int argc, char **argv)
     }
   }
 
-  if (!initialize_storage())
+  if (! initialize_storage())
   {
     /* Error message already printed */
     return 1;
   }
 
-  if (!port_specified)
+  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");
@@ -286,7 +330,7 @@ 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];
@@ -297,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)
@@ -357,17 +400,16 @@ static void work(void)
           assert(c != NULL);
           fds[max_poll].events= 0;
 
-          switch (memcached_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 */
+
+          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;