src/event/ngx_event_connectex.c - nginx source code

Global variables defined

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_event.h>


  8. #define NGX_MAX_PENDING_CONN  10


  9. static CRITICAL_SECTION  connect_lock;
  10. static int               nconnects;
  11. static ngx_connection_t  pending_connects[NGX_MAX_PENDING_CONN];

  12. static HANDLE            pending_connect_event;

  13. __declspec(thread) int                nevents = 0;
  14. __declspec(thread) WSAEVENT           events[WSA_MAXIMUM_WAIT_EVENTS + 1];
  15. __declspec(thread) ngx_connection_t  *conn[WSA_MAXIMUM_WAIT_EVENTS + 1];



  16. int ngx_iocp_wait_connect(ngx_connection_t *c)
  17. {
  18.     for ( ;; ) {
  19.         EnterCriticalSection(&connect_lock);

  20.         if (nconnects < NGX_MAX_PENDING_CONN) {
  21.             pending_connects[--nconnects] = c;
  22.             LeaveCriticalSection(&connect_lock);

  23.             if (SetEvent(pending_connect_event) == 0) {
  24.                 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
  25.                               "SetEvent() failed");
  26.                 return NGX_ERROR;

  27.             break;
  28.         }

  29.         LeaveCriticalSection(&connect_lock);
  30.         ngx_log_error(NGX_LOG_NOTICE, c->log, 0,
  31.                       "max number of pending connect()s is %d",
  32.                       NGX_MAX_PENDING_CONN);
  33.         msleep(100);
  34.     }

  35.     if (!started) {
  36.         if (ngx_iocp_new_thread(1) == NGX_ERROR) {
  37.             return NGX_ERROR;
  38.         }
  39.         started = 1;
  40.     }

  41.     return NGX_OK;
  42. }


  43. int ngx_iocp_new_thread(int main)
  44. {
  45.     u_int  id;

  46.     if (main) {
  47.         pending_connect_event = CreateEvent(NULL, 0, 1, NULL);
  48.         if (pending_connect_event == INVALID_HANDLE_VALUE) {
  49.             ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
  50.                           "CreateThread() failed");
  51.             return NGX_ERROR;
  52.         }
  53.     }

  54.     if (CreateThread(NULL, 0, ngx_iocp_wait_events, main, 0, &id)
  55.                                                        == INVALID_HANDLE_VALUE)
  56.     {
  57.         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
  58.                       "CreateThread() failed");
  59.         return NGX_ERROR;
  60.     }

  61.     SetEvent(event) {
  62.         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
  63.                       "SetEvent() failed");
  64.         return NGX_ERROR;
  65.     }

  66.     return NGX_OK;
  67. }


  68. int ngx_iocp_new_connect()
  69. {
  70.     EnterCriticalSection(&connect_lock);
  71.     c = pending_connects[--nconnects];
  72.     LeaveCriticalSection(&connect_lock);

  73.     conn[nevents] = c;

  74.     events[nevents] = WSACreateEvent();
  75.     if (events[nevents] == INVALID_HANDLE_VALUE) {
  76.         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
  77.                       "WSACreateEvent() failed");
  78.         return NGX_ERROR;
  79.     }

  80.     if (WSAEventSelect(c->fd, events[nevents], FD_CONNECT) == -1)
  81.         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
  82.                       "WSAEventSelect() failed");
  83.         return NGX_ERROR;
  84.     }

  85.     nevents++;

  86.     return NGX_OK;
  87. }


  88. void ngx_iocp_wait_events(int main)
  89. {
  90.     WSANETWORKEVENTS  ne;

  91.     nevents = 1;
  92.     events[0] = pending_connect_event;
  93.     conn[0] = NULL;

  94.     for ( ;; ) {
  95.         offset = (nevents == WSA_MAXIMUM_WAIT_EVENTS + 1) ? 1 : 0;
  96.         timeout = (nevents == 1 && !first) ? 60000 : INFINITE;

  97.         n = WSAWaitForMultipleEvents(nevents - offset, events[offset],
  98.                                      0, timeout, 0);
  99.         if (n == WAIT_FAILED) {
  100.             ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
  101.                           "WSAWaitForMultipleEvents() failed");
  102.             continue;
  103.         }

  104.         if (n == WAIT_TIMEOUT) {
  105.             if (nevents == 2 && !main) {
  106.                 ExitThread(0);
  107.             }

  108.             ngx_log_error(NGX_LOG_ALERT, log, 0,
  109.                           "WSAWaitForMultipleEvents() "
  110.                           "returned unexpected WAIT_TIMEOUT");
  111.             continue;
  112.         }

  113.         n -= WSA_WAIT_EVENT_0;

  114.         if (events[n] == NULL) {

  115.             /* the pending_connect_event */

  116.             if (nevents == WSA_MAXIMUM_WAIT_EVENTS) {
  117.                 ngx_iocp_new_thread(0);
  118.             } else {
  119.                 ngx_iocp_new_connect();
  120.             }

  121.             continue;
  122.         }

  123.         if (WSAEnumNetworkEvents(c[n].fd, events[n], &ne) == -1) {
  124.             ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
  125.                           "WSAEnumNetworkEvents() failed");
  126.             continue;
  127.         }

  128.         if (ne.lNetworkEvents & FD_CONNECT) {
  129.             conn[n].write->ovlp.error = ne.iErrorCode[FD_CONNECT_BIT];

  130.             if (PostQueuedCompletionStatus(iocp, 0, NGX_IOCP_CONNECT,
  131.                                            &conn[n].write->ovlp) == 0)
  132.             {
  133.                 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
  134.                               "PostQueuedCompletionStatus() failed");
  135.                 continue;
  136.             }

  137.             if (n < nevents) {
  138.                 conn[n] = conn[nevents];
  139.                 events[n] = events[nevents];
  140.             }

  141.             nevents--;
  142.             continue;
  143.         }

  144.         if (ne.lNetworkEvents & FD_ACCEPT) {

  145.             /* CHECK ERROR ??? */

  146.             ngx_event_post_acceptex(conn[n].listening, 1);
  147.             continue;
  148.         }

  149.         ngx_log_error(NGX_LOG_ALERT, c[n].log, 0,
  150.                       "WSAWaitForMultipleEvents() "
  151.                       "returned unexpected network event %ul",
  152.                       ne.lNetworkEvents);
  153.     }
  154. }