gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r8336 - in libmicrohttpd/src: daemon include testcurl


From: gnunet
Subject: [GNUnet-SVN] r8336 - in libmicrohttpd/src: daemon include testcurl
Date: Tue, 17 Mar 2009 00:59:31 -0600

Author: grothoff
Date: 2009-03-17 00:59:31 -0600 (Tue, 17 Mar 2009)
New Revision: 8336

Modified:
   libmicrohttpd/src/daemon/daemon.c
   libmicrohttpd/src/daemon/internal.h
   libmicrohttpd/src/include/microhttpd.h
   libmicrohttpd/src/testcurl/daemontest_get.c
   libmicrohttpd/src/testcurl/daemontest_get_chunked.c
   libmicrohttpd/src/testcurl/daemontest_iplimit.c
   libmicrohttpd/src/testcurl/daemontest_large_put.c
   libmicrohttpd/src/testcurl/daemontest_post.c
   libmicrohttpd/src/testcurl/daemontest_post_loop.c
   libmicrohttpd/src/testcurl/daemontest_postform.c
   libmicrohttpd/src/testcurl/daemontest_process_headers.c
   libmicrohttpd/src/testcurl/daemontest_put.c
   libmicrohttpd/src/testcurl/daemontest_put_chunked.c
Log:
adding thread pool functionality -- code by Richard Alimi


Modified: libmicrohttpd/src/daemon/daemon.c
===================================================================
--- libmicrohttpd/src/daemon/daemon.c   2009-03-17 06:57:36 UTC (rev 8335)
+++ libmicrohttpd/src/daemon/daemon.c   2009-03-17 06:59:31 UTC (rev 8336)
@@ -1,6 +1,6 @@
 /*
   This file is part of libmicrohttpd
-  (C) 2007, 2008 Daniel Pittman and Christian Grothoff
+  (C) 2007, 2008, 2009 Daniel Pittman and Christian Grothoff
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -187,8 +187,8 @@
   if (daemon->per_ip_connection_limit == 0)
     return MHD_YES;
 
-  key = (struct MHD_IPCount*) malloc (sizeof(*key));
-  if (!key)
+  key = malloc (sizeof(*key));
+  if (NULL == key)
     return MHD_NO;
 
   /* Initialize key */
@@ -625,7 +625,7 @@
 #endif
 #endif
   connection = malloc (sizeof (struct MHD_Connection));
-  if (connection == NULL)
+  if (NULL == connection)
     {
 #if HAVE_MESSAGES
       MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
@@ -1017,6 +1017,7 @@
   const struct sockaddr *servaddr = NULL;
   socklen_t addrlen;
   enum MHD_OPTION opt;
+  unsigned int i;
 
   if ((port == 0) || (dh == NULL))
     return NULL;
@@ -1080,6 +1081,9 @@
             va_arg (ap, LogCallback);
           retVal->uri_log_callback_cls = va_arg (ap, void *);
           break;
+        case MHD_OPTION_THREAD_POOL_SIZE:
+          retVal->worker_pool_size = va_arg (ap, unsigned int);
+          break;
 #if HTTPS_SUPPORT
         case MHD_OPTION_PROTOCOL_VERSION:
           _set_priority (&retVal->priority_cache->protocol,
@@ -1126,6 +1130,17 @@
         }
     }
 
+  /* Thread pooling currently works only with internal select thread model */
+  if ((0 == (options & MHD_USE_SELECT_INTERNALLY))
+      && (retVal->worker_pool_size > 0))
+    {
+#if HAVE_MESSAGES
+      FPRINTF (stderr,
+               "MHD thread pooling only works with 
MHD_USE_SELECT_INTERNALLY\n");
+#endif
+      return NULL;
+    }
+
   if ((options & MHD_USE_IPv6) != 0)
 #if HAVE_INET6
     socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0);
@@ -1235,7 +1250,8 @@
     }
 #endif
   if (((0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
-       (0 != (options & MHD_USE_SELECT_INTERNALLY)))
+       ((0 != (options & MHD_USE_SELECT_INTERNALLY))
+        && (0 == retVal->worker_pool_size)))
       && (0 !=
           pthread_create (&retVal->pid, NULL, &MHD_select_thread, retVal)))
     {
@@ -1248,6 +1264,87 @@
       CLOSE (socket_fd);
       return NULL;
     }
+  else if (retVal->worker_pool_size > 0)
+    {
+      /* Coarse-grained count of connections per thread (note error
+       * due to integer division). Also keep track of how many
+       * connections are leftover after an equal split. */
+      unsigned int conns_per_thread = retVal->max_connections
+                                      / retVal->worker_pool_size;
+      unsigned int leftover_conns = retVal->max_connections
+                                    % retVal->worker_pool_size;
+
+      /* Allocate memory for pooled objects */
+      retVal->worker_pool = malloc (sizeof (*retVal->worker_pool)
+                                    * retVal->worker_pool_size);
+
+      /* Start the workers in the pool */
+      for (i = 0; i < retVal->worker_pool_size; ++i)
+        {
+          /* Create copy of the Daemon object for each worker */
+          struct MHD_Daemon *d = (struct MHD_Daemon*) malloc (sizeof (*d));
+          if (!d)
+            {
+#if HAVE_MESSAGES
+              MHD_DLOG (retVal,
+                        "Failed to copy daemon object: %d\n", STRERROR 
(errno));
+#endif
+              goto thread_failed;
+            }
+          memcpy (d, retVal, sizeof (*d));
+
+          /* Adjust pooling params for worker daemons; note that memcpy()
+           * has already copied MHD_USE_SELECT_INTERNALLY thread model into
+           * the worker threads. */
+          d->master = retVal;
+          d->worker_pool_size = 0;
+          d->worker_pool = NULL;
+
+          /* Divide available connections evenly amongst the threads.
+           * Thread indexes in [0, leftover_conns) each get one of the
+           * leftover connections. */
+          d->max_connections = conns_per_thread;
+          if (i < leftover_conns)
+            ++d->max_connections;
+
+          /* Spawn the worker thread */
+          if (0 != pthread_create (&d->pid, NULL, &MHD_select_thread, d))
+            {
+#if HAVE_MESSAGES
+              MHD_DLOG (retVal,
+                        "Failed to create pool thread: %d\n", STRERROR 
(errno));
+#endif
+              /* Free memory for this worker; cleanup below handles
+               * all previously-created workers. */
+              free (d);
+              goto thread_failed;
+            }
+
+          retVal->worker_pool[i] = d;
+          continue;
+
+thread_failed:
+          /* If no worker threads created, then shut down normally. Calling
+           * MHD_stop_daemon (as we do below) doesn't work here since it
+           * assumes a 0-sized thread pool means we had been in the default
+           * MHD_USE_SELECT_INTERNALLY mode. */
+          if (i == 0)
+            {
+              CLOSE (socket_fd);
+              pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
+              free (retVal);
+              return NULL;
+            }
+
+          /* Shutdown worker threads we've already created. Pretend
+           * as though we had fully initialized our daemon, but
+           * with a smaller number of threads than had been
+           * requested. */
+          retVal->worker_pool_size = i - 1;
+          MHD_stop_daemon (retVal);
+          return NULL;
+        }
+    }
   return retVal;
 }
 
@@ -1281,20 +1378,42 @@
 {
   void *unused;
   int fd;
+  unsigned int i;
 
   if (daemon == NULL)
     return;
   daemon->shutdown = MHD_YES;
   fd = daemon->socket_fd;
   daemon->socket_fd = -1;
+
+  /* Prepare workers for shutdown */
+  for (i = 0; i < daemon->worker_pool_size; ++i)
+    {
+      daemon->worker_pool[i]->shutdown = MHD_YES;
+      daemon->worker_pool[i]->socket_fd = -1;
+    }
+
 #if DEBUG_CLOSE
 #if HAVE_MESSAGES
   MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
 #endif
 #endif
   CLOSE (fd);
+
+  /* Signal workers to stop and clean them up */
+  for (i = 0; i < daemon->worker_pool_size; ++i)
+    pthread_kill (daemon->worker_pool[i]->pid, SIGALRM);
+  for (i = 0; i < daemon->worker_pool_size; ++i)
+    {
+      pthread_join (daemon->worker_pool[i]->pid, &unused);
+      MHD_close_connections (daemon->worker_pool[i]);
+      free (daemon->worker_pool[i]);
+    }
+  free (daemon->worker_pool);
+
   if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
-      (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
+      ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))
+        && (0 == daemon->worker_pool_size)))
     {
       pthread_kill (daemon->pid, SIGALRM);
       pthread_join (daemon->pid, &unused);

Modified: libmicrohttpd/src/daemon/internal.h
===================================================================
--- libmicrohttpd/src/daemon/internal.h 2009-03-17 06:57:36 UTC (rev 8335)
+++ libmicrohttpd/src/daemon/internal.h 2009-03-17 06:59:31 UTC (rev 8336)
@@ -775,6 +775,16 @@
    * Pointer to master daemon (NULL if this is the master)
    */
   struct MHD_Daemon *master;
+
+  /**
+   * Worker daemons (one per thread)
+   */
+  struct MHD_Daemon **worker_pool;
+
+  /**
+   * Number of worker daemons
+   */
+  unsigned int worker_pool_size;
 };
 
 

Modified: libmicrohttpd/src/include/microhttpd.h
===================================================================
--- libmicrohttpd/src/include/microhttpd.h      2009-03-17 06:57:36 UTC (rev 
8335)
+++ libmicrohttpd/src/include/microhttpd.h      2009-03-17 06:59:31 UTC (rev 
8336)
@@ -429,8 +429,17 @@
    * if it was compiled without the "--enable-messages"
    * flag being set.
    */
-  MHD_OPTION_EXTERNAL_LOGGER = 13
+  MHD_OPTION_EXTERNAL_LOGGER = 13,
 
+  /**
+   * Number (unsigned int) of threads in thread pool. Enable
+   * thread pooling by setting this value to to something
+   * greater than 1. Currently, thread model must be
+   * MHD_USE_SELECT_INTERNALLY if thread pooling is enabled
+   * (MHD_start_daemon returns NULL for an unsupported thread
+   * model).
+   */
+  MHD_OPTION_THREAD_POOL_SIZE = 14,
 };
 
 /**

Modified: libmicrohttpd/src/testcurl/daemontest_get.c
===================================================================
--- libmicrohttpd/src/testcurl/daemontest_get.c 2009-03-17 06:57:36 UTC (rev 
8335)
+++ libmicrohttpd/src/testcurl/daemontest_get.c 2009-03-17 06:59:31 UTC (rev 
8336)
@@ -188,7 +188,56 @@
   return 0;
 }
 
+static int
+testMultithreadedPoolGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLcode errornum;
 
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        1081, NULL, NULL, &ahc_echo, "GET",
+                        MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 64;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 128;
+  return 0;
+}
+
 static int
 testExternalGet ()
 {
@@ -323,6 +372,7 @@
     return 2;
   errorCount += testInternalGet ();
   errorCount += testMultithreadedGet ();
+  errorCount += testMultithreadedPoolGet ();
   errorCount += testExternalGet ();
   if (errorCount != 0)
     fprintf (stderr, "Error (code: %u)\n", errorCount);

Modified: libmicrohttpd/src/testcurl/daemontest_get_chunked.c
===================================================================
--- libmicrohttpd/src/testcurl/daemontest_get_chunked.c 2009-03-17 06:57:36 UTC 
(rev 8335)
+++ libmicrohttpd/src/testcurl/daemontest_get_chunked.c 2009-03-17 06:59:31 UTC 
(rev 8336)
@@ -227,7 +227,49 @@
   return validate (cbc, 64);
 }
 
+static int
+testMultithreadedPoolGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLcode errornum;
 
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        1081, NULL, NULL, &ahc_echo, "GET",
+                        MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  return validate (cbc, 64);
+}
+
 static int
 testExternalGet ()
 {
@@ -354,6 +396,7 @@
     return 2;
   errorCount += testInternalGet ();
   errorCount += testMultithreadedGet ();
+  errorCount += testMultithreadedPoolGet ();
   errorCount += testExternalGet ();
   if (errorCount != 0)
     fprintf (stderr, "Error (code: %u)\n", errorCount);

Modified: libmicrohttpd/src/testcurl/daemontest_iplimit.c
===================================================================
--- libmicrohttpd/src/testcurl/daemontest_iplimit.c     2009-03-17 06:57:36 UTC 
(rev 8335)
+++ libmicrohttpd/src/testcurl/daemontest_iplimit.c     2009-03-17 06:59:31 UTC 
(rev 8336)
@@ -90,6 +90,103 @@
 }
 
 static int
+testMultithreadedGet ()
+{
+  struct MHD_Daemon *d;
+  char buf[2048];
+  int k;
+
+  /* Test only valid for HTTP/1.1 (uses persistent connections) */
+  if (!oneone)
+    return 0;
+
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        1081, NULL, NULL, &ahc_echo, "GET",
+                        MHD_OPTION_PER_IP_CONNECTION_LIMIT, 2,
+                        MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+
+  for (k = 0; k < 3; ++k)
+    {
+      struct CBC cbc[3];
+      CURL *cenv[3];
+      int i;
+
+      for (i = 0; i < 3; ++i)
+        {
+          CURL *c;
+          CURLcode errornum;
+ 
+          cenv[i] = c = curl_easy_init ();
+          cbc[i].buf = buf;
+          cbc[i].size = 2048;
+          cbc[i].pos = 0;
+
+          curl_easy_setopt (c, CURLOPT_URL, 
"http://localhost:1081/hello_world";);
+          curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+          curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc[i]);
+          curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+          curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+          curl_easy_setopt (c, CURLOPT_FORBID_REUSE, 0L);
+          curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+          curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+          // NOTE: use of CONNECTTIMEOUT without also
+          //   setting NOSIGNAL results in really weird
+          //   crashes on my system!
+          curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+
+          errornum = curl_easy_perform (c);
+          if (CURLE_OK != errornum && i < 2
+              || CURLE_OK == errornum && i == 2)
+            {
+              int j;
+
+              /* First 2 should succeed */
+              if (i < 2)
+                fprintf (stderr,
+                         "curl_easy_perform failed: `%s'\n",
+                         curl_easy_strerror (errornum));
+
+              /* Last request should have failed */
+              else
+                fprintf (stderr,
+                         "No error on IP address over limit\n");
+
+              for (j = 0; j < i; ++j)
+                curl_easy_cleanup (cenv[j]);
+              MHD_stop_daemon (d);
+              return 32;
+            }
+        }
+
+      /* Cleanup the environments */
+      for (i = 0; i < 3; ++i)
+        curl_easy_cleanup (cenv[i]);
+
+      sleep(2);
+
+      for (i = 0; i < 2; ++i)
+        {
+          if (cbc[i].pos != strlen ("/hello_world"))
+            {
+              MHD_stop_daemon (d);
+              return 64;
+            }
+          if (0 != strncmp ("/hello_world", cbc[i].buf, strlen 
("/hello_world")))
+            {
+              MHD_stop_daemon (d);
+              return 128;
+            }
+        }
+
+
+    }
+  MHD_stop_daemon (d);
+  return 0;
+}
+
+static int
 testMultithreadedPoolGet ()
 {
   struct MHD_Daemon *d;
@@ -103,6 +200,7 @@
   d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
                         1081, NULL, NULL, &ahc_echo, "GET",
                         MHD_OPTION_PER_IP_CONNECTION_LIMIT, 2,
+                        MHD_OPTION_THREAD_POOL_SIZE, 4,
                         MHD_OPTION_END);
   if (d == NULL)
     return 16;
@@ -194,6 +292,7 @@
   oneone = NULL != strstr (argv[0], "11");
   if (0 != curl_global_init (CURL_GLOBAL_WIN32))
     return 2;
+  errorCount += testMultithreadedGet ();
   errorCount += testMultithreadedPoolGet ();
   if (errorCount != 0)
     fprintf (stderr, "Error (code: %u)\n", errorCount);

Modified: libmicrohttpd/src/testcurl/daemontest_large_put.c
===================================================================
--- libmicrohttpd/src/testcurl/daemontest_large_put.c   2009-03-17 06:57:36 UTC 
(rev 8335)
+++ libmicrohttpd/src/testcurl/daemontest_large_put.c   2009-03-17 06:59:31 UTC 
(rev 8336)
@@ -245,7 +245,66 @@
   return 0;
 }
 
+static int
+testMultithreadedPoolPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  struct CBC cbc;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  CURLcode errornum;
+  char buf[2048];
 
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        1081,
+                        NULL, NULL, &ahc_echo, &done_flag,
+                        MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  curl_easy_setopt (c, CURLOPT_INFILESIZE, (long) PUT_SIZE);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    {
+      fprintf (stderr, "Got invalid response `%.*s'\n", cbc.pos, cbc.buf);
+      return 64;
+    }
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 128;
+  return 0;
+}
+
 static int
 testExternalPut ()
 {
@@ -394,6 +453,7 @@
   memset (put_buffer, 1, PUT_SIZE);
   errorCount += testInternalPut ();
   errorCount += testMultithreadedPut ();
+  errorCount += testMultithreadedPoolPut ();
   errorCount += testExternalPut ();
   free (put_buffer);
   if (errorCount != 0)

Modified: libmicrohttpd/src/testcurl/daemontest_post.c
===================================================================
--- libmicrohttpd/src/testcurl/daemontest_post.c        2009-03-17 06:57:36 UTC 
(rev 8335)
+++ libmicrohttpd/src/testcurl/daemontest_post.c        2009-03-17 06:59:31 UTC 
(rev 8336)
@@ -231,7 +231,59 @@
   return 0;
 }
 
+static int
+testMultithreadedPoolPost ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLcode errornum;
 
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        1081, NULL, NULL, &ahc_echo, NULL,
+                        MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
+  curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
+  curl_easy_setopt (c, CURLOPT_POST, 1L);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 64;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 128;
+  return 0;
+}
+
 static int
 testExternalPost ()
 {
@@ -369,6 +421,7 @@
     return 2;
   errorCount += testInternalPost ();
   errorCount += testMultithreadedPost ();
+  errorCount += testMultithreadedPoolPost ();
   errorCount += testExternalPost ();
   if (errorCount != 0)
     fprintf (stderr, "Error (code: %u)\n", errorCount);

Modified: libmicrohttpd/src/testcurl/daemontest_post_loop.c
===================================================================
--- libmicrohttpd/src/testcurl/daemontest_post_loop.c   2009-03-17 06:57:36 UTC 
(rev 8335)
+++ libmicrohttpd/src/testcurl/daemontest_post_loop.c   2009-03-17 06:59:31 UTC 
(rev 8336)
@@ -225,7 +225,71 @@
   return 0;
 }
 
+static int
+testMultithreadedPoolPost ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLcode errornum;
+  int i;
+  char url[1024];
 
+  cbc.buf = buf;
+  cbc.size = 2048;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        1081, NULL, NULL, &ahc_echo, NULL,
+                        MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  for (i = 0; i < LOOPCOUNT; i++)
+    {
+      if (99 == i % 100)
+        fprintf (stderr, ".");
+      c = curl_easy_init ();
+      cbc.pos = 0;
+      buf[0] = '\0';
+      sprintf (url, "http://localhost:1081/hw%d";, i);
+      curl_easy_setopt (c, CURLOPT_URL, url);
+      curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+      curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+      curl_easy_setopt (c, CURLOPT_POSTFIELDS, POST_DATA);
+      curl_easy_setopt (c, CURLOPT_POSTFIELDSIZE, strlen (POST_DATA));
+      curl_easy_setopt (c, CURLOPT_POST, 1L);
+      curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+      curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+      if (oneone)
+        curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+      else
+        curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+      curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+      // NOTE: use of CONNECTTIMEOUT without also
+      //   setting NOSIGNAL results in really weird
+      //   crashes on my system!
+      curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+      if (CURLE_OK != (errornum = curl_easy_perform (c)))
+        {
+          fprintf (stderr,
+                   "curl_easy_perform failed: `%s'\n",
+                   curl_easy_strerror (errornum));
+          curl_easy_cleanup (c);
+          MHD_stop_daemon (d);
+          return 32;
+        }
+      curl_easy_cleanup (c);
+      if ((buf[0] != 'O') || (buf[1] != 'K'))
+        {
+          MHD_stop_daemon (d);
+          return 64;
+        }
+    }
+  MHD_stop_daemon (d);
+  if (LOOPCOUNT >= 99)
+    fprintf (stderr, "\n");
+  return 0;
+}
+
 static int
 testExternalPost ()
 {
@@ -379,6 +443,7 @@
     return 2;
   errorCount += testInternalPost ();
   errorCount += testMultithreadedPost ();
+  errorCount += testMultithreadedPoolPost ();
   errorCount += testExternalPost ();
   if (errorCount != 0)
     fprintf (stderr, "Error (code: %u)\n", errorCount);

Modified: libmicrohttpd/src/testcurl/daemontest_postform.c
===================================================================
--- libmicrohttpd/src/testcurl/daemontest_postform.c    2009-03-17 06:57:36 UTC 
(rev 8335)
+++ libmicrohttpd/src/testcurl/daemontest_postform.c    2009-03-17 06:59:31 UTC 
(rev 8336)
@@ -251,7 +251,61 @@
   return 0;
 }
 
+static int
+testMultithreadedPoolPost ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLcode errornum;
+  struct curl_httppost *pd;
 
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        1081, NULL, NULL, &ahc_echo, NULL,
+                        MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  pd = make_form ();
+  curl_easy_setopt (c, CURLOPT_HTTPPOST, pd);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 5L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      curl_formfree (pd);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  curl_formfree (pd);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 64;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 128;
+  return 0;
+}
+
 static int
 testExternalPost ()
 {
@@ -394,6 +448,7 @@
     return 2;
   errorCount += testInternalPost ();
   errorCount += testMultithreadedPost ();
+  errorCount += testMultithreadedPoolPost ();
   errorCount += testExternalPost ();
   if (errorCount != 0)
     fprintf (stderr, "Error (code: %u)\n", errorCount);

Modified: libmicrohttpd/src/testcurl/daemontest_process_headers.c
===================================================================
--- libmicrohttpd/src/testcurl/daemontest_process_headers.c     2009-03-17 
06:57:36 UTC (rev 8335)
+++ libmicrohttpd/src/testcurl/daemontest_process_headers.c     2009-03-17 
06:59:31 UTC (rev 8336)
@@ -235,7 +235,56 @@
   return 0;
 }
 
+static int
+testMultithreadedPoolGet ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  CURLcode errornum;
 
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        21080, NULL, NULL, &ahc_echo, "GET",
+                        MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:21080/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  /* NOTE: use of CONNECTTIMEOUT without also
+     setting NOSIGNAL results in really weird
+     crashes on my system! */
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 64;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 128;
+  return 0;
+}
+
 static int
 testExternalGet ()
 {
@@ -370,6 +419,7 @@
     return 2;
   errorCount += testInternalGet ();
   errorCount += testMultithreadedGet ();
+  errorCount += testMultithreadedPoolGet ();
   errorCount += testExternalGet ();
   if (errorCount != 0)
     fprintf (stderr, "Error (code: %u)\n", errorCount);

Modified: libmicrohttpd/src/testcurl/daemontest_put.c
===================================================================
--- libmicrohttpd/src/testcurl/daemontest_put.c 2009-03-17 06:57:36 UTC (rev 
8335)
+++ libmicrohttpd/src/testcurl/daemontest_put.c 2009-03-17 06:59:31 UTC (rev 
8336)
@@ -223,7 +223,65 @@
   return 0;
 }
 
+static int
+testMultithreadedPoolPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  CURLcode errornum;
 
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        1081,
+                        NULL, NULL, &ahc_echo, &done_flag,
+                        MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:1081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  if (oneone)
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  else
+    curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 64;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 128;
+
+  return 0;
+}
+
+
 static int
 testExternalPut ()
 {
@@ -365,6 +423,7 @@
     return 2;
   errorCount += testInternalPut ();
   errorCount += testMultithreadedPut ();
+  errorCount += testMultithreadedPoolPut ();
   errorCount += testExternalPut ();
   if (errorCount != 0)
     fprintf (stderr, "Error (code: %u)\n", errorCount);

Modified: libmicrohttpd/src/testcurl/daemontest_put_chunked.c
===================================================================
--- libmicrohttpd/src/testcurl/daemontest_put_chunked.c 2009-03-17 06:57:36 UTC 
(rev 8335)
+++ libmicrohttpd/src/testcurl/daemontest_put_chunked.c 2009-03-17 06:59:31 UTC 
(rev 8336)
@@ -232,7 +232,65 @@
   return 0;
 }
 
+static int
+testMultithreadedPoolPut ()
+{
+  struct MHD_Daemon *d;
+  CURL *c;
+  char buf[2048];
+  struct CBC cbc;
+  unsigned int pos = 0;
+  int done_flag = 0;
+  CURLcode errornum;
 
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+  d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
+                        11081,
+                        NULL, NULL, &ahc_echo, &done_flag,
+                        MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
+  if (d == NULL)
+    return 16;
+  c = curl_easy_init ();
+  curl_easy_setopt (c, CURLOPT_URL, "http://localhost:11081/hello_world";);
+  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (c, CURLOPT_READDATA, &pos);
+  curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
+  /*
+     // by not giving the file size, we force chunking!
+     curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
+   */
+  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
+  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 15L);
+  // NOTE: use of CONNECTTIMEOUT without also
+  //   setting NOSIGNAL results in really weird
+  //   crashes on my system!
+  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
+  if (CURLE_OK != (errornum = curl_easy_perform (c)))
+    {
+      fprintf (stderr,
+               "curl_easy_perform failed: `%s'\n",
+               curl_easy_strerror (errornum));
+      curl_easy_cleanup (c);
+      MHD_stop_daemon (d);
+      return 32;
+    }
+  curl_easy_cleanup (c);
+  MHD_stop_daemon (d);
+  if (cbc.pos != strlen ("/hello_world"))
+    return 64;
+  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
+    return 128;
+
+  return 0;
+}
+
+
 static int
 testExternalPut ()
 {
@@ -373,6 +431,7 @@
     return 2;
   errorCount += testInternalPut ();
   errorCount += testMultithreadedPut ();
+  errorCount += testMultithreadedPoolPut ();
   errorCount += testExternalPut ();
   if (errorCount != 0)
     fprintf (stderr, "Error (code: %u)\n", errorCount);





reply via email to

[Prev in Thread] Current Thread [Next in Thread]