blob: 86d763b7115769b03d4581d5cebdb4a45690f2d3 [file] [log] [blame]
Igor Sysoev73009772003-02-06 17:21:13 +00001
Igor Sysoeve4a25262003-06-06 14:59:20 +00002/*
3 * Copyright (C) 2002-2003 Igor Sysoev, http://sysoev.ru
4 */
5
6
Igor Sysoev73009772003-02-06 17:21:13 +00007#include <ngx_config.h>
Igor Sysoev73009772003-02-06 17:21:13 +00008#include <ngx_core.h>
Igor Sysoev73009772003-02-06 17:21:13 +00009#include <ngx_event.h>
Igor Sysoev239baac2003-06-11 15:28:34 +000010#include <ngx_iocp_module.h>
Igor Sysoev73009772003-02-06 17:21:13 +000011
12
Igor Sysoev9d639522003-07-07 06:11:50 +000013static int ngx_iocp_init(ngx_cycle_t *cycle);
14static void ngx_iocp_done(ngx_cycle_t *cycle);
Igor Sysoeve4a25262003-06-06 14:59:20 +000015static int ngx_iocp_add_event(ngx_event_t *ev, int event, u_int key);
Igor Sysoev239baac2003-06-11 15:28:34 +000016static int ngx_iocp_del_connection(ngx_connection_t *c);
Igor Sysoeve4a25262003-06-06 14:59:20 +000017static int ngx_iocp_process_events(ngx_log_t *log);
Igor Sysoev9d639522003-07-07 06:11:50 +000018static void *ngx_iocp_create_conf(ngx_cycle_t *cycle);
19static char *ngx_iocp_init_conf(ngx_cycle_t *cycle, void *conf);
Igor Sysoev73009772003-02-06 17:21:13 +000020
21
Igor Sysoeve4a25262003-06-06 14:59:20 +000022static ngx_str_t iocp_name = ngx_string("iocp");
23
24static ngx_command_t ngx_iocp_commands[] = {
25
26 {ngx_string("iocp_threads"),
27 NGX_EVENT_CONF|NGX_CONF_TAKE1,
28 ngx_conf_set_num_slot,
29 0,
30 offsetof(ngx_iocp_conf_t, threads),
31 NULL},
32
Igor Sysoev239baac2003-06-11 15:28:34 +000033 {ngx_string("acceptex"),
34 NGX_EVENT_CONF|NGX_CONF_TAKE1,
35 ngx_conf_set_num_slot,
36 0,
37 offsetof(ngx_iocp_conf_t, acceptex),
38 NULL},
39
40 {ngx_string("acceptex_read"),
41 NGX_EVENT_CONF|NGX_CONF_TAKE1,
42 ngx_conf_set_flag_slot,
43 0,
44 offsetof(ngx_iocp_conf_t, acceptex_read),
45 NULL},
46
Igor Sysoeve4a25262003-06-06 14:59:20 +000047 ngx_null_command
48};
49
50
51ngx_event_module_t ngx_iocp_module_ctx = {
52 &iocp_name,
53 ngx_iocp_create_conf, /* create configuration */
54 ngx_iocp_init_conf, /* init configuration */
55
56 {
57 ngx_iocp_add_event, /* add an event */
58 NULL, /* delete an event */
59 NULL, /* enable an event */
60 NULL, /* disable an event */
61 NULL, /* add an connection */
Igor Sysoev239baac2003-06-11 15:28:34 +000062 ngx_iocp_del_connection, /* delete an connection */
Igor Sysoeve4a25262003-06-06 14:59:20 +000063 ngx_iocp_process_events, /* process the events */
64 ngx_iocp_init, /* init the events */
65 ngx_iocp_done /* done the events */
66 }
67
68};
69
70ngx_module_t ngx_iocp_module = {
71 NGX_MODULE,
72 &ngx_iocp_module_ctx, /* module context */
73 ngx_iocp_commands, /* module directives */
74 NGX_EVENT_MODULE, /* module type */
Igor Sysoev9d639522003-07-07 06:11:50 +000075 NULL, /* init module */
76 NULL /* init child */
Igor Sysoeve4a25262003-06-06 14:59:20 +000077};
78
79
80static HANDLE iocp;
81
82
Igor Sysoev9d639522003-07-07 06:11:50 +000083static int ngx_iocp_init(ngx_cycle_t *cycle)
Igor Sysoev73009772003-02-06 17:21:13 +000084{
Igor Sysoeve4a25262003-06-06 14:59:20 +000085 ngx_iocp_conf_t *cf;
86
Igor Sysoev9d639522003-07-07 06:11:50 +000087 cf = ngx_event_get_conf(cycle->conf_ctx, ngx_iocp_module);
Igor Sysoev73009772003-02-06 17:21:13 +000088
89 if (iocp == NULL) {
Igor Sysoev9d639522003-07-07 06:11:50 +000090 iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0,
91 cf->threads);
92 }
93
94 if (iocp == NULL) {
95 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
Igor Sysoev73009772003-02-06 17:21:13 +000096 "CreateIoCompletionPort() failed");
97 return NGX_ERROR;
98 }
99
Igor Sysoev9d639522003-07-07 06:11:50 +0000100 if (ngx_event_timer_init(cycle) == NGX_ERROR) {
Igor Sysoev73009772003-02-06 17:21:13 +0000101 return NGX_ERROR;
102 }
103
Igor Sysoev9d639522003-07-07 06:11:50 +0000104 ngx_io = ngx_os_io;
105
Igor Sysoeve4a25262003-06-06 14:59:20 +0000106 ngx_event_actions = ngx_iocp_module_ctx.actions;
Igor Sysoev73009772003-02-06 17:21:13 +0000107
Igor Sysoev0a280a32003-10-12 16:49:16 +0000108 ngx_event_flags = NGX_USE_AIO_EVENT|NGX_USE_IOCP_EVENT;
Igor Sysoev73009772003-02-06 17:21:13 +0000109
110 return NGX_OK;
111}
112
113
Igor Sysoev9d639522003-07-07 06:11:50 +0000114static void ngx_iocp_done(ngx_cycle_t *cycle)
Igor Sysoeve4a25262003-06-06 14:59:20 +0000115{
116 if (CloseHandle(iocp) == -1) {
Igor Sysoev9d639522003-07-07 06:11:50 +0000117 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
118 "iocp CloseHandle() failed");
Igor Sysoeve4a25262003-06-06 14:59:20 +0000119 }
120
Igor Sysoev9d639522003-07-07 06:11:50 +0000121 iocp = NULL;
122
123 ngx_event_timer_done(cycle);
Igor Sysoeve4a25262003-06-06 14:59:20 +0000124}
125
126
127static int ngx_iocp_add_event(ngx_event_t *ev, int event, u_int key)
Igor Sysoev73009772003-02-06 17:21:13 +0000128{
129 ngx_connection_t *c;
130
131 c = (ngx_connection_t *) ev->data;
132
Igor Sysoev239baac2003-06-11 15:28:34 +0000133 c->read->active = 1;
134 c->write->active = 1;
135
136 ngx_log_debug(ev->log, "iocp add: %d, %d:%08x" _ c->fd _ key _ &ev->ovlp);
Igor Sysoev73009772003-02-06 17:21:13 +0000137
Igor Sysoeve4a25262003-06-06 14:59:20 +0000138 if (CreateIoCompletionPort((HANDLE) c->fd, iocp, key, 0) == NULL) {
Igor Sysoev239baac2003-06-11 15:28:34 +0000139 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
Igor Sysoev73009772003-02-06 17:21:13 +0000140 "CreateIoCompletionPort() failed");
141 return NGX_ERROR;
142 }
143
144 return NGX_OK;
145}
146
147
Igor Sysoev239baac2003-06-11 15:28:34 +0000148static int ngx_iocp_del_connection(ngx_connection_t *c)
149{
150 if (CancelIo((HANDLE) c->fd) == 0) {
151 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, "CancelIo() failed");
152 return NGX_ERROR;
153 }
154
155 return NGX_OK;
156}
157
158
Igor Sysoeve4a25262003-06-06 14:59:20 +0000159static int ngx_iocp_process_events(ngx_log_t *log)
Igor Sysoev73009772003-02-06 17:21:13 +0000160{
161 int rc;
Igor Sysoeve4a25262003-06-06 14:59:20 +0000162 u_int key;
Igor Sysoev73009772003-02-06 17:21:13 +0000163 size_t bytes;
164 ngx_err_t err;
165 ngx_msec_t timer, delta;
Igor Sysoeve4a25262003-06-06 14:59:20 +0000166 ngx_event_t *ev;
Igor Sysoev73009772003-02-06 17:21:13 +0000167 ngx_event_ovlp_t *ovlp;
168
Igor Sysoev73009772003-02-06 17:21:13 +0000169 timer = ngx_event_find_timer();
170
171 if (timer) {
172 delta = ngx_msec();
173
174 } else {
175 timer = INFINITE;
176 delta = 0;
177 }
178
179 ngx_log_debug(log, "iocp timer: %d" _ timer);
180
Igor Sysoeve4a25262003-06-06 14:59:20 +0000181 rc = GetQueuedCompletionStatus(iocp, &bytes, (LPDWORD) &key,
Igor Sysoev73009772003-02-06 17:21:13 +0000182 (LPOVERLAPPED *) &ovlp, timer);
Igor Sysoeve4a25262003-06-06 14:59:20 +0000183
Igor Sysoev239baac2003-06-11 15:28:34 +0000184 ngx_log_debug(log, "iocp: %d, %d, %d:%08x" _ rc _ bytes _ key _ ovlp);
Igor Sysoeve4a25262003-06-06 14:59:20 +0000185
Igor Sysoev73009772003-02-06 17:21:13 +0000186 if (rc == 0) {
Igor Sysoev73009772003-02-06 17:21:13 +0000187 err = ngx_errno;
Igor Sysoev9d639522003-07-07 06:11:50 +0000188 } else {
189 err = 0;
190 }
Igor Sysoev73009772003-02-06 17:21:13 +0000191
Igor Sysoev9d639522003-07-07 06:11:50 +0000192 if (timer != INFINITE) {
193 delta = ngx_msec() - delta;
194 ngx_event_expire_timers(delta);
195 }
196
197 if (err) {
Igor Sysoev73009772003-02-06 17:21:13 +0000198 if (ovlp == NULL) {
199 if (err != WAIT_TIMEOUT) {
200 ngx_log_error(NGX_LOG_ALERT, log, err,
201 "GetQueuedCompletionStatus() failed");
202
203 return NGX_ERROR;
204 }
205
206 } else {
207 ovlp->error = err;
208 }
209 }
210
Igor Sysoev73009772003-02-06 17:21:13 +0000211 if (ovlp) {
212 ev = ovlp->event;
213
214ngx_log_debug(log, "iocp ev: %08x" _ ev);
215
Igor Sysoeve4a25262003-06-06 14:59:20 +0000216 switch (key) {
217 case NGX_IOCP_IO:
Igor Sysoev73009772003-02-06 17:21:13 +0000218 ev->ready = 1;
Igor Sysoeve4a25262003-06-06 14:59:20 +0000219 break;
220
221 case NGX_IOCP_ACCEPT:
Igor Sysoev239baac2003-06-11 15:28:34 +0000222 if (bytes) {
223 ev->ready = 1;
224 }
Igor Sysoeve4a25262003-06-06 14:59:20 +0000225 break;
Igor Sysoev73009772003-02-06 17:21:13 +0000226 }
227
Igor Sysoev239baac2003-06-11 15:28:34 +0000228 ev->available = bytes;
229
Igor Sysoeve4a25262003-06-06 14:59:20 +0000230ngx_log_debug(log, "iocp ev handler: %08x" _ ev->event_handler);
Igor Sysoev73009772003-02-06 17:21:13 +0000231
Igor Sysoev1c13c662003-05-20 15:37:55 +0000232 ev->event_handler(ev);
Igor Sysoev73009772003-02-06 17:21:13 +0000233 }
234
Igor Sysoev73009772003-02-06 17:21:13 +0000235 return NGX_OK;
236}
Igor Sysoeve4a25262003-06-06 14:59:20 +0000237
238
Igor Sysoev9d639522003-07-07 06:11:50 +0000239static void *ngx_iocp_create_conf(ngx_cycle_t *cycle)
Igor Sysoeve4a25262003-06-06 14:59:20 +0000240{
241 ngx_iocp_conf_t *cf;
242
Igor Sysoev9d639522003-07-07 06:11:50 +0000243 ngx_test_null(cf, ngx_palloc(cycle->pool, sizeof(ngx_iocp_conf_t)),
Igor Sysoeve4a25262003-06-06 14:59:20 +0000244 NGX_CONF_ERROR);
245
246 cf->threads = NGX_CONF_UNSET;
Igor Sysoev239baac2003-06-11 15:28:34 +0000247 cf->acceptex = NGX_CONF_UNSET;
248 cf->acceptex_read = NGX_CONF_UNSET;
Igor Sysoeve4a25262003-06-06 14:59:20 +0000249
250 return cf;
251}
252
253
Igor Sysoev9d639522003-07-07 06:11:50 +0000254static char *ngx_iocp_init_conf(ngx_cycle_t *cycle, void *conf)
Igor Sysoeve4a25262003-06-06 14:59:20 +0000255{
256 ngx_iocp_conf_t *cf = conf;
257
258 ngx_conf_init_value(cf->threads, 0);
Igor Sysoev239baac2003-06-11 15:28:34 +0000259 ngx_conf_init_value(cf->acceptex, 10);
260 ngx_conf_init_value(cf->acceptex_read, 1);
Igor Sysoeve4a25262003-06-06 14:59:20 +0000261
262 return NGX_CONF_OK;
263}