comparison src/stream/ngx_stream_upstream_zone_module.c @ 6115:61d7ae76647d

Stream: port from NGINX+.
author Ruslan Ermilov <ru@nginx.com>
date Mon, 20 Apr 2015 13:05:11 +0300
parents
children caa103acf180
comparison
equal deleted inserted replaced
6114:4a640716f4e2 6115:61d7ae76647d
1
2 /*
3 * Copyright (C) Ruslan Ermilov
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_stream.h>
11
12
13 static char *ngx_stream_upstream_zone(ngx_conf_t *cf, ngx_command_t *cmd,
14 void *conf);
15 static ngx_int_t ngx_stream_upstream_init_zone(ngx_shm_zone_t *shm_zone,
16 void *data);
17
18
19 static ngx_command_t ngx_stream_upstream_zone_commands[] = {
20
21 { ngx_string("zone"),
22 NGX_STREAM_UPS_CONF|NGX_CONF_TAKE2,
23 ngx_stream_upstream_zone,
24 0,
25 0,
26 NULL },
27
28 ngx_null_command
29 };
30
31
32 static ngx_stream_module_t ngx_stream_upstream_zone_module_ctx = {
33 NULL, /* create main configuration */
34 NULL, /* init main configuration */
35
36 NULL, /* create server configuration */
37 NULL, /* merge server configuration */
38 };
39
40
41 ngx_module_t ngx_stream_upstream_zone_module = {
42 NGX_MODULE_V1,
43 &ngx_stream_upstream_zone_module_ctx, /* module context */
44 ngx_stream_upstream_zone_commands, /* module directives */
45 NGX_STREAM_MODULE, /* module type */
46 NULL, /* init master */
47 NULL, /* init module */
48 NULL, /* init process */
49 NULL, /* init thread */
50 NULL, /* exit thread */
51 NULL, /* exit process */
52 NULL, /* exit master */
53 NGX_MODULE_V1_PADDING
54 };
55
56
57 static char *
58 ngx_stream_upstream_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
59 {
60 ssize_t size;
61 ngx_str_t *value;
62 ngx_stream_upstream_srv_conf_t *uscf;
63
64 uscf = ngx_stream_conf_get_module_srv_conf(cf, ngx_stream_upstream_module);
65
66 value = cf->args->elts;
67
68 if (!value[1].len) {
69 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
70 "invalid zone name \"%V\"", &value[1]);
71 return NGX_CONF_ERROR;
72 }
73
74 size = ngx_parse_size(&value[2]);
75
76 if (size == NGX_ERROR) {
77 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
78 "invalid zone size \"%V\"", &value[2]);
79 return NGX_CONF_ERROR;
80 }
81
82 if (size < (ssize_t) (8 * ngx_pagesize)) {
83 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
84 "zone \"%V\" is too small", &value[1]);
85 return NGX_CONF_ERROR;
86 }
87
88 uscf->shm_zone = ngx_shared_memory_add(cf, &value[1], size,
89 &ngx_stream_upstream_module);
90 if (uscf->shm_zone == NULL) {
91 return NGX_CONF_ERROR;
92 }
93
94 if (uscf->shm_zone->data) {
95 uscf = uscf->shm_zone->data;
96
97 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
98 "upstream \"%V\" in %s:%ui "
99 "is already bound to zone \"%V\"",
100 &uscf->host, uscf->file_name, uscf->line,
101 &value[1]);
102 return NGX_CONF_ERROR;
103 }
104
105 uscf->shm_zone->init = ngx_stream_upstream_init_zone;
106 uscf->shm_zone->data = uscf;
107
108 uscf->shm_zone->noreuse = 1;
109
110 return NGX_CONF_OK;
111 }
112
113
114 static ngx_int_t
115 ngx_stream_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data)
116 {
117 ngx_stream_upstream_srv_conf_t *ouscf = data;
118
119 size_t len;
120 ngx_slab_pool_t *shpool;
121 ngx_stream_upstream_rr_peer_t *peer, **peerp;
122 ngx_stream_upstream_rr_peers_t *peers, *backup;
123 ngx_stream_upstream_srv_conf_t *uscf;
124
125 uscf = shm_zone->data;
126
127 if (ouscf) {
128 ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0,
129 "zone \"%V\" cannot be reused", &shm_zone->shm.name);
130 return NGX_ERROR;
131 }
132
133 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
134
135 if (shm_zone->shm.exists) {
136 return NGX_ERROR;
137 }
138
139
140 /* copy peers to shared memory */
141
142 len = sizeof(" in upstream zone \"\"") + shm_zone->shm.name.len;
143
144 shpool->log_ctx = ngx_slab_alloc(shpool, len);
145 if (shpool->log_ctx == NULL) {
146 return NGX_ERROR;
147 }
148
149 ngx_sprintf(shpool->log_ctx, " in upstream zone \"%V\"%Z",
150 &shm_zone->shm.name);
151
152 peers = ngx_slab_alloc(shpool, sizeof(ngx_stream_upstream_rr_peers_t));
153 if (peers == NULL) {
154 return NGX_ERROR;
155 }
156
157 ngx_memcpy(peers, uscf->peer.data, sizeof(ngx_stream_upstream_rr_peers_t));
158
159 peers->shpool = shpool;
160
161 for (peerp = &peers->peer; *peerp; peerp = &peer->next) {
162 /* pool is unlocked */
163 peer = ngx_slab_calloc_locked(shpool,
164 sizeof(ngx_stream_upstream_rr_peer_t));
165 if (peer == NULL) {
166 return NGX_ERROR;
167 }
168
169 ngx_memcpy(peer, *peerp, sizeof(ngx_stream_upstream_rr_peer_t));
170
171 *peerp = peer;
172 }
173
174 if (peers->next == NULL) {
175 goto done;
176 }
177
178 backup = ngx_slab_alloc(shpool, sizeof(ngx_stream_upstream_rr_peers_t));
179 if (backup == NULL) {
180 return NGX_ERROR;
181 }
182
183 ngx_memcpy(backup, peers->next, sizeof(ngx_stream_upstream_rr_peers_t));
184
185 backup->shpool = shpool;
186
187 for (peerp = &backup->peer; *peerp; peerp = &peer->next) {
188 /* pool is unlocked */
189 peer = ngx_slab_calloc_locked(shpool,
190 sizeof(ngx_stream_upstream_rr_peer_t));
191 if (peer == NULL) {
192 return NGX_ERROR;
193 }
194
195 ngx_memcpy(peer, *peerp, sizeof(ngx_stream_upstream_rr_peer_t));
196
197 *peerp = peer;
198 }
199
200 peers->next = backup;
201
202 done:
203
204 uscf->peer.data = peers;
205
206 return NGX_OK;
207 }