Blame src/testcurl/perf_get.c

Packit 875988
/*
Packit 875988
     This file is part of libmicrohttpd
Packit 875988
     Copyright (C) 2007, 2009, 2011 Christian Grothoff
Packit 875988
Packit 875988
     libmicrohttpd is free software; you can redistribute it and/or modify
Packit 875988
     it under the terms of the GNU General Public License as published
Packit 875988
     by the Free Software Foundation; either version 2, or (at your
Packit 875988
     option) any later version.
Packit 875988
Packit 875988
     libmicrohttpd is distributed in the hope that it will be useful, but
Packit 875988
     WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 875988
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 875988
     General Public License for more details.
Packit 875988
Packit 875988
     You should have received a copy of the GNU General Public License
Packit 875988
     along with libmicrohttpd; see the file COPYING.  If not, write to the
Packit 875988
     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit 875988
     Boston, MA 02110-1301, USA.
Packit 875988
*/
Packit 875988
Packit 875988
/**
Packit 875988
 * @file perf_get.c
Packit 875988
 * @brief benchmark simple GET operations (sequential access).
Packit 875988
 *        Note that we run libcurl in the same process at the
Packit 875988
 *        same time, so the execution time given is the combined
Packit 875988
 *        time for both MHD and libcurl; it is quite possible
Packit 875988
 *        that more time is spend with libcurl than with MHD,
Packit 875988
 *        so the performance scores calculated with this code
Packit 875988
 *        should NOT be used to compare with other HTTP servers
Packit 875988
 *        (since MHD is actually better); only the relative
Packit 875988
 *        scores between MHD versions are meaningful.
Packit 875988
 *        Furthermore, this code ONLY tests MHD processing
Packit 875988
 *        a single request at a time.  This is again
Packit 875988
 *        not universally meaningful (i.e. when comparing
Packit 875988
 *        multithreaded vs. single-threaded or select/poll).
Packit 875988
 * @author Christian Grothoff
Packit 875988
 */
Packit 875988
Packit 875988
#include "MHD_config.h"
Packit 875988
#include "platform.h"
Packit 875988
#include <curl/curl.h>
Packit 875988
#include <microhttpd.h>
Packit 875988
#include <stdlib.h>
Packit 875988
#include <string.h>
Packit 875988
#include <time.h>
Packit 875988
#include "gauger.h"
Packit 875988
Packit 875988
#ifndef WINDOWS
Packit 875988
#include <unistd.h>
Packit 875988
#include <sys/socket.h>
Packit 875988
#endif
Packit 875988
Packit 875988
#if defined(CPU_COUNT) && (CPU_COUNT+0) < 2
Packit 875988
#undef CPU_COUNT
Packit 875988
#endif
Packit 875988
#if !defined(CPU_COUNT)
Packit 875988
#define CPU_COUNT 2
Packit 875988
#endif
Packit 875988
Packit 875988
/**
Packit 875988
 * How many rounds of operations do we do for each
Packit 875988
 * test?
Packit 875988
 */
Packit 875988
#define ROUNDS 500
Packit 875988
Packit 875988
/**
Packit 875988
 * Do we use HTTP 1.1?
Packit 875988
 */
Packit 875988
static int oneone;
Packit 875988
Packit 875988
/**
Packit 875988
 * Response to return (re-used).
Packit 875988
 */
Packit 875988
static struct MHD_Response *response;
Packit 875988
Packit 875988
/**
Packit 875988
 * Time this round was started.
Packit 875988
 */
Packit 875988
static unsigned long long start_time;
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Get the current timestamp
Packit 875988
 *
Packit 875988
 * @return current time in ms
Packit 875988
 */
Packit 875988
static unsigned long long
Packit 875988
now ()
Packit 875988
{
Packit 875988
  struct timeval tv;
Packit 875988
Packit 875988
  gettimeofday (&tv, NULL);
Packit 875988
  return (((unsigned long long) tv.tv_sec * 1000LL) +
Packit 875988
	  ((unsigned long long) tv.tv_usec / 1000LL));
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Start the timer.
Packit 875988
 */
Packit 875988
static void
Packit 875988
start_timer()
Packit 875988
{
Packit 875988
  start_time = now ();
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Stop the timer and report performance
Packit 875988
 *
Packit 875988
 * @param desc description of the threading mode we used
Packit 875988
 */
Packit 875988
static void
Packit 875988
stop (const char *desc)
Packit 875988
{
Packit 875988
  double rps = ((double) (ROUNDS * 1000)) / ((double) (now() - start_time));
Packit 875988
Packit 875988
  fprintf (stderr,
Packit 875988
	   "Sequential GETs using %s: %f %s\n",
Packit 875988
	   desc,
Packit 875988
	   rps,
Packit 875988
	   "requests/s");
Packit 875988
  GAUGER (desc,
Packit 875988
	  "Sequential GETs",
Packit 875988
	  rps,
Packit 875988
	  "requests/s");
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
struct CBC
Packit 875988
{
Packit 875988
  char *buf;
Packit 875988
  size_t pos;
Packit 875988
  size_t size;
Packit 875988
};
Packit 875988
Packit 875988
Packit 875988
static size_t
Packit 875988
copyBuffer (void *ptr,
Packit 875988
	    size_t size, size_t nmemb,
Packit 875988
	    void *ctx)
Packit 875988
{
Packit 875988
  struct CBC *cbc = ctx;
Packit 875988
Packit 875988
  if (cbc->pos + size * nmemb > cbc->size)
Packit 875988
    return 0;                   /* overflow */
Packit 875988
  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
Packit 875988
  cbc->pos += size * nmemb;
Packit 875988
  return size * nmemb;
Packit 875988
}
Packit 875988
Packit 875988
static int
Packit 875988
ahc_echo (void *cls,
Packit 875988
          struct MHD_Connection *connection,
Packit 875988
          const char *url,
Packit 875988
          const char *method,
Packit 875988
          const char *version,
Packit 875988
          const char *upload_data, size_t *upload_data_size,
Packit 875988
          void **unused)
Packit 875988
{
Packit 875988
  static int ptr;
Packit 875988
  const char *me = cls;
Packit 875988
  int ret;
Packit 875988
  (void)url;(void)version;                      /* Unused. Silent compiler warning. */
Packit 875988
  (void)upload_data;(void)upload_data_size;     /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  if (0 != strcmp (me, method))
Packit 875988
    return MHD_NO;              /* unexpected method */
Packit 875988
  if (&ptr != *unused)
Packit 875988
    {
Packit 875988
      *unused = &pt;;
Packit 875988
      return MHD_YES;
Packit 875988
    }
Packit 875988
  *unused = NULL;
Packit 875988
  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
Packit 875988
  if (ret == MHD_NO)
Packit 875988
    abort ();
Packit 875988
  return ret;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
testInternalGet (int port, int poll_flag)
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  CURL *c;
Packit 875988
  char buf[2048];
Packit 875988
  struct CBC cbc;
Packit 875988
  CURLcode errornum;
Packit 875988
  unsigned int i;
Packit 875988
  char url[64];
Packit 875988
Packit 875988
  if (MHD_NO != MHD_is_feature_supported(MHD_FEATURE_AUTODETECT_BIND_PORT))
Packit 875988
    port = 0;
Packit 875988
Packit 875988
  cbc.buf = buf;
Packit 875988
  cbc.size = 2048;
Packit 875988
  d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG  | poll_flag,
Packit 875988
                        port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 1;
Packit 875988
  if (0 == port)
Packit 875988
    {
Packit 875988
      const union MHD_DaemonInfo *dinfo;
Packit 875988
      dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
Packit 875988
      if (NULL == dinfo || 0 == dinfo->port)
Packit 875988
        { MHD_stop_daemon (d); return 32; }
Packit 875988
      port = (int)dinfo->port;
Packit 875988
    }
Packit 875988
  sprintf(url, "http://127.0.0.1:%d/hello_world", port);
Packit 875988
  start_timer ();
Packit 875988
  for (i=0;i
Packit 875988
    {
Packit 875988
      cbc.pos = 0;
Packit 875988
      c = curl_easy_init ();
Packit 875988
      curl_easy_setopt (c, CURLOPT_URL, url);
Packit 875988
      curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
Packit 875988
      curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
Packit 875988
      curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
Packit 875988
      curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
Packit 875988
      curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
Packit 875988
      if (oneone)
Packit 875988
	curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
Packit 875988
      else
Packit 875988
	curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
Packit 875988
      /* NOTE: use of CONNECTTIMEOUT without also
Packit 875988
	 setting NOSIGNAL results in really weird
Packit 875988
	 crashes on my system!*/
Packit 875988
      curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
Packit 875988
      if (CURLE_OK != (errornum = curl_easy_perform (c)))
Packit 875988
	{
Packit 875988
	  fprintf (stderr,
Packit 875988
		   "curl_easy_perform failed: `%s'\n",
Packit 875988
		   curl_easy_strerror (errornum));
Packit 875988
	  curl_easy_cleanup (c);
Packit 875988
	  MHD_stop_daemon (d);
Packit 875988
	  return 2;
Packit 875988
	}
Packit 875988
      curl_easy_cleanup (c);
Packit 875988
    }
Packit 875988
  stop (poll_flag == MHD_USE_AUTO ? "internal thread with 'auto'" :
Packit 875988
        poll_flag == MHD_USE_POLL ? "internal thread with poll()" :
Packit 875988
	poll_flag == MHD_USE_EPOLL ? "internal thread with epoll" : "internal thread with select()");
Packit 875988
  MHD_stop_daemon (d);
Packit 875988
  if (cbc.pos != strlen ("/hello_world"))
Packit 875988
    return 4;
Packit 875988
  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
Packit 875988
    return 8;
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
testMultithreadedGet (int port, int poll_flag)
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  CURL *c;
Packit 875988
  char buf[2048];
Packit 875988
  struct CBC cbc;
Packit 875988
  CURLcode errornum;
Packit 875988
  unsigned int i;
Packit 875988
  char url[64];
Packit 875988
Packit 875988
  if (MHD_NO != MHD_is_feature_supported(MHD_FEATURE_AUTODETECT_BIND_PORT))
Packit 875988
    port = 0;
Packit 875988
Packit 875988
  cbc.buf = buf;
Packit 875988
  cbc.size = 2048;
Packit 875988
  d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG  | poll_flag,
Packit 875988
                        port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 16;
Packit 875988
  if (0 == port)
Packit 875988
    {
Packit 875988
      const union MHD_DaemonInfo *dinfo;
Packit 875988
      dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
Packit 875988
      if (NULL == dinfo || 0 == dinfo->port)
Packit 875988
        { MHD_stop_daemon (d); return 32; }
Packit 875988
      port = (int)dinfo->port;
Packit 875988
    }
Packit 875988
  sprintf(url, "http://127.0.0.1:%d/hello_world", port);
Packit 875988
  start_timer ();
Packit 875988
  for (i=0;i
Packit 875988
    {
Packit 875988
      cbc.pos = 0;
Packit 875988
      c = curl_easy_init ();
Packit 875988
      curl_easy_setopt (c, CURLOPT_URL, url);
Packit 875988
      curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
Packit 875988
      curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
Packit 875988
      curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
Packit 875988
      curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
Packit 875988
      if (oneone)
Packit 875988
	curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
Packit 875988
      else
Packit 875988
	curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
Packit 875988
      curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
Packit 875988
      /* NOTE: use of CONNECTTIMEOUT without also
Packit 875988
	 setting NOSIGNAL results in really weird
Packit 875988
	 crashes on my system! */
Packit 875988
      curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
Packit 875988
      if (CURLE_OK != (errornum = curl_easy_perform (c)))
Packit 875988
	{
Packit 875988
	  fprintf (stderr,
Packit 875988
		   "curl_easy_perform failed: `%s'\n",
Packit 875988
		   curl_easy_strerror (errornum));
Packit 875988
	  curl_easy_cleanup (c);
Packit 875988
	  MHD_stop_daemon (d);
Packit 875988
	  return 32;
Packit 875988
	}
Packit 875988
      curl_easy_cleanup (c);
Packit 875988
    }
Packit 875988
  stop ((poll_flag & MHD_USE_AUTO) ? "internal thread with 'auto' and thread per connection" :
Packit 875988
        (poll_flag & MHD_USE_POLL) ? "internal thread with poll() and thread per connection" :
Packit 875988
	(poll_flag & MHD_USE_EPOLL) ? "internal thread with epoll and thread per connection" :
Packit 875988
	    "internal thread with select() and thread per connection");
Packit 875988
  MHD_stop_daemon (d);
Packit 875988
  if (cbc.pos != strlen ("/hello_world"))
Packit 875988
    return 64;
Packit 875988
  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
Packit 875988
    return 128;
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
static int
Packit 875988
testMultithreadedPoolGet (int port, int poll_flag)
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  CURL *c;
Packit 875988
  char buf[2048];
Packit 875988
  struct CBC cbc;
Packit 875988
  CURLcode errornum;
Packit 875988
  unsigned int i;
Packit 875988
  char url[64];
Packit 875988
Packit 875988
  if (MHD_NO != MHD_is_feature_supported(MHD_FEATURE_AUTODETECT_BIND_PORT))
Packit 875988
    port = 0;
Packit 875988
Packit 875988
  cbc.buf = buf;
Packit 875988
  cbc.size = 2048;
Packit 875988
  d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | poll_flag,
Packit 875988
                        port, NULL, NULL, &ahc_echo, "GET",
Packit 875988
                        MHD_OPTION_THREAD_POOL_SIZE, CPU_COUNT, MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 16;
Packit 875988
  if (0 == port)
Packit 875988
    {
Packit 875988
      const union MHD_DaemonInfo *dinfo;
Packit 875988
      dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
Packit 875988
      if (NULL == dinfo || 0 == dinfo->port)
Packit 875988
        { MHD_stop_daemon (d); return 32; }
Packit 875988
      port = (int)dinfo->port;
Packit 875988
    }
Packit 875988
  sprintf(url, "http://127.0.0.1:%d/hello_world", port);
Packit 875988
  start_timer ();
Packit 875988
  for (i=0;i
Packit 875988
    {
Packit 875988
      cbc.pos = 0;
Packit 875988
      c = curl_easy_init ();
Packit 875988
      curl_easy_setopt (c, CURLOPT_URL, url);
Packit 875988
      curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
Packit 875988
      curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
Packit 875988
      curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
Packit 875988
      curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
Packit 875988
      if (oneone)
Packit 875988
	curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
Packit 875988
      else
Packit 875988
	curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
Packit 875988
      curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
Packit 875988
      /* NOTE: use of CONNECTTIMEOUT without also
Packit 875988
	 setting NOSIGNAL results in really weird
Packit 875988
	 crashes on my system!*/
Packit 875988
      curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
Packit 875988
      if (CURLE_OK != (errornum = curl_easy_perform (c)))
Packit 875988
	{
Packit 875988
	  fprintf (stderr,
Packit 875988
		   "curl_easy_perform failed: `%s'\n",
Packit 875988
		   curl_easy_strerror (errornum));
Packit 875988
	  curl_easy_cleanup (c);
Packit 875988
	  MHD_stop_daemon (d);
Packit 875988
	  return 32;
Packit 875988
	}
Packit 875988
      curl_easy_cleanup (c);
Packit 875988
    }
Packit 875988
  stop (0 != (poll_flag & MHD_USE_AUTO) ? "internal thread pool with 'auto'" :
Packit 875988
        0 != (poll_flag & MHD_USE_POLL) ? "internal thread pool with poll()" :
Packit 875988
	0 != (poll_flag & MHD_USE_EPOLL) ? "internal thread pool with epoll" : "internal thread pool with select()");
Packit 875988
  MHD_stop_daemon (d);
Packit 875988
  if (cbc.pos != strlen ("/hello_world"))
Packit 875988
    return 64;
Packit 875988
  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
Packit 875988
    return 128;
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
static int
Packit 875988
testExternalGet (int port)
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  CURL *c;
Packit 875988
  char buf[2048];
Packit 875988
  struct CBC cbc;
Packit 875988
  CURLM *multi;
Packit 875988
  CURLMcode mret;
Packit 875988
  fd_set rs;
Packit 875988
  fd_set ws;
Packit 875988
  fd_set es;
Packit 875988
  MHD_socket maxsock;
Packit 875988
#ifdef MHD_WINSOCK_SOCKETS
Packit 875988
  int maxposixs; /* Max socket number unused on W32 */
Packit 875988
#else  /* MHD_POSIX_SOCKETS */
Packit 875988
#define maxposixs maxsock
Packit 875988
#endif /* MHD_POSIX_SOCKETS */
Packit 875988
  int running;
Packit 875988
  struct CURLMsg *msg;
Packit 875988
  time_t start;
Packit 875988
  struct timeval tv;
Packit 875988
  unsigned int i;
Packit 875988
  char url[64];
Packit 875988
Packit 875988
  if (MHD_NO != MHD_is_feature_supported(MHD_FEATURE_AUTODETECT_BIND_PORT))
Packit 875988
    port = 0;
Packit 875988
Packit 875988
  multi = NULL;
Packit 875988
  cbc.buf = buf;
Packit 875988
  cbc.size = 2048;
Packit 875988
  d = MHD_start_daemon (MHD_USE_ERROR_LOG,
Packit 875988
                        port, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 256;
Packit 875988
  if (0 == port)
Packit 875988
    {
Packit 875988
      const union MHD_DaemonInfo *dinfo;
Packit 875988
      dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
Packit 875988
      if (NULL == dinfo || 0 == dinfo->port)
Packit 875988
        { MHD_stop_daemon (d); return 32; }
Packit 875988
      port = (int)dinfo->port;
Packit 875988
    }
Packit 875988
  sprintf(url, "http://127.0.0.1:%d/hello_world", port);
Packit 875988
  start_timer ();
Packit 875988
  multi = curl_multi_init ();
Packit 875988
  if (multi == NULL)
Packit 875988
    {
Packit 875988
      MHD_stop_daemon (d);
Packit 875988
      return 512;
Packit 875988
    }
Packit 875988
  for (i=0;i
Packit 875988
    {
Packit 875988
      cbc.pos = 0;
Packit 875988
      c = curl_easy_init ();
Packit 875988
      curl_easy_setopt (c, CURLOPT_URL, url);
Packit 875988
      curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
Packit 875988
      curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
Packit 875988
      curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
Packit 875988
      if (oneone)
Packit 875988
	curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
Packit 875988
      else
Packit 875988
	curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
Packit 875988
      curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
Packit 875988
      curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
Packit 875988
      /* NOTE: use of CONNECTTIMEOUT without also
Packit 875988
	 setting NOSIGNAL results in really weird
Packit 875988
	 crashes on my system! */
Packit 875988
      curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
Packit 875988
      mret = curl_multi_add_handle (multi, c);
Packit 875988
      if (mret != CURLM_OK)
Packit 875988
	{
Packit 875988
	  curl_multi_cleanup (multi);
Packit 875988
	  curl_easy_cleanup (c);
Packit 875988
	  MHD_stop_daemon (d);
Packit 875988
	  return 1024;
Packit 875988
	}
Packit 875988
      start = time (NULL);
Packit 875988
      while ((time (NULL) - start < 5) && (c != NULL))
Packit 875988
	{
Packit 875988
	  maxsock = MHD_INVALID_SOCKET;
Packit 875988
	  maxposixs = -1;
Packit 875988
	  FD_ZERO (&rs);
Packit 875988
	  FD_ZERO (&ws);
Packit 875988
	  FD_ZERO (&es);
Packit 875988
	  curl_multi_perform (multi, &running);
Packit 875988
	  mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxposixs);
Packit 875988
	  if (mret != CURLM_OK)
Packit 875988
	    {
Packit 875988
	      curl_multi_remove_handle (multi, c);
Packit 875988
	      curl_multi_cleanup (multi);
Packit 875988
	      curl_easy_cleanup (c);
Packit 875988
	      MHD_stop_daemon (d);
Packit 875988
	      return 2048;
Packit 875988
	    }
Packit 875988
	  if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxsock))
Packit 875988
	    {
Packit 875988
	      curl_multi_remove_handle (multi, c);
Packit 875988
	      curl_multi_cleanup (multi);
Packit 875988
	      curl_easy_cleanup (c);
Packit 875988
	      MHD_stop_daemon (d);
Packit 875988
	      return 4096;
Packit 875988
	    }
Packit 875988
	  tv.tv_sec = 0;
Packit 875988
	  tv.tv_usec = 1000;
Packit 875988
	  if (-1 == select (maxposixs + 1, &rs, &ws, &es, &tv))
Packit 875988
            {
Packit 875988
#ifdef MHD_POSIX_SOCKETS
Packit 875988
              if (EINTR != errno)
Packit 875988
                abort ();
Packit 875988
#else
Packit 875988
              if (WSAEINVAL != WSAGetLastError() || 0 != rs.fd_count || 0 != ws.fd_count || 0 != es.fd_count)
Packit 875988
                abort ();
Packit 875988
              Sleep (1000);
Packit 875988
#endif
Packit 875988
            }
Packit 875988
	  curl_multi_perform (multi, &running);
Packit 875988
	  if (running == 0)
Packit 875988
	    {
Packit 875988
	      msg = curl_multi_info_read (multi, &running);
Packit 875988
	      if (msg == NULL)
Packit 875988
		break;
Packit 875988
	      if (msg->msg == CURLMSG_DONE)
Packit 875988
		{
Packit 875988
		  if (msg->data.result != CURLE_OK)
Packit 875988
		    printf ("%s failed at %s:%d: `%s'\n",
Packit 875988
			    "curl_multi_perform",
Packit 875988
			    __FILE__,
Packit 875988
			    __LINE__, curl_easy_strerror (msg->data.result));
Packit 875988
		  curl_multi_remove_handle (multi, c);
Packit 875988
		  curl_easy_cleanup (c);
Packit 875988
		  c = NULL;
Packit 875988
		}
Packit 875988
	    }
Packit 875988
	  /* two possibilities here; as select sets are
Packit 875988
	     tiny, this makes virtually no difference
Packit 875988
	     in actual runtime right now, even though the
Packit 875988
	     number of select calls is virtually cut in half
Packit 875988
	     (and 'select' is the most expensive of our system
Packit 875988
	     calls according to 'strace') */
Packit 875988
	  if (0)
Packit 875988
	    MHD_run (d);
Packit 875988
	  else
Packit 875988
	    MHD_run_from_select (d, &rs, &ws, &es);
Packit 875988
	}
Packit 875988
      if (NULL != c)
Packit 875988
	{
Packit 875988
	  curl_multi_remove_handle (multi, c);
Packit 875988
	  curl_easy_cleanup (c);
Packit 875988
	  fprintf (stderr, "Timeout!?\n");
Packit 875988
	}
Packit 875988
    }
Packit 875988
  stop ("external select");
Packit 875988
  if (multi != NULL)
Packit 875988
    {
Packit 875988
      curl_multi_cleanup (multi);
Packit 875988
    }
Packit 875988
  MHD_stop_daemon (d);
Packit 875988
  if (cbc.pos != strlen ("/hello_world"))
Packit 875988
    return 8192;
Packit 875988
  if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
Packit 875988
    return 16384;
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
int
Packit 875988
main (int argc, char *const *argv)
Packit 875988
{
Packit 875988
  unsigned int errorCount = 0;
Packit 875988
  int port = 1130;
Packit 875988
  (void)argc;   /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  oneone = (NULL != strrchr (argv[0], (int) '/')) ?
Packit 875988
    (NULL != strstr (strrchr (argv[0], (int) '/'), "11")) : 0;
Packit 875988
  if (oneone)
Packit 875988
    port += 15;
Packit 875988
  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
Packit 875988
    return 2;
Packit 875988
  response = MHD_create_response_from_buffer (strlen ("/hello_world"),
Packit 875988
					      "/hello_world",
Packit 875988
					      MHD_RESPMEM_MUST_COPY);
Packit 875988
  errorCount += testExternalGet (port++);
Packit 875988
  errorCount += testInternalGet (port++, MHD_USE_AUTO);
Packit 875988
  errorCount += testMultithreadedGet (port++, MHD_USE_AUTO);
Packit 875988
  errorCount += testMultithreadedPoolGet (port++, MHD_USE_AUTO);
Packit 875988
  errorCount += testInternalGet (port++, 0);
Packit 875988
  errorCount += testMultithreadedGet (port++, 0);
Packit 875988
  errorCount += testMultithreadedPoolGet (port++, 0);
Packit 875988
  if (MHD_YES == MHD_is_feature_supported(MHD_FEATURE_POLL))
Packit 875988
    {
Packit 875988
      errorCount += testInternalGet(port++, MHD_USE_POLL);
Packit 875988
      errorCount += testMultithreadedGet(port++, MHD_USE_POLL);
Packit 875988
      errorCount += testMultithreadedPoolGet(port++, MHD_USE_POLL);
Packit 875988
    }
Packit 875988
  if (MHD_YES == MHD_is_feature_supported(MHD_FEATURE_EPOLL))
Packit 875988
    {
Packit 875988
      errorCount += testInternalGet(port++, MHD_USE_EPOLL);
Packit 875988
      errorCount += testMultithreadedPoolGet(port++, MHD_USE_EPOLL);
Packit 875988
    }
Packit 875988
  MHD_destroy_response (response);
Packit 875988
  if (errorCount != 0)
Packit 875988
    fprintf (stderr, "Error (code: %u)\n", errorCount);
Packit 875988
  curl_global_cleanup ();
Packit 875988
  return errorCount != 0;       /* 0 == pass */
Packit 875988
}