annotate src/core/ngx_hash.c @ 56:3050baa54a26 NGINX_0_1_28

nginx 0.1.28 *) Bugfix: nginx hogs CPU while proxying the huge files. *) Bugfix: nginx could not be built by gcc 4.0 on Linux.
author Igor Sysoev <http://sysoev.ru>
date Fri, 08 Apr 2005 00:00:00 +0400
parents
children b55cbf18157e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
56
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
1
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
2 /*
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
3 * Copyright (C) Igor Sysoev
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
4 */
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
5
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
6
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
7 #include <ngx_config.h>
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
8 #include <ngx_core.h>
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
9
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
10
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
11 ngx_int_t
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
12 ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names)
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
13 {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
14 u_char *p;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
15 ngx_str_t *n, *bucket;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
16 ngx_uint_t i, key, size, best, *test, buckets, min_buckets;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
17
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
18 test = ngx_alloc(hash->max_size * sizeof(ngx_uint_t), pool->log);
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
19 if (test == NULL) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
20 return NGX_ERROR;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
21 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
22
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
23 min_buckets = hash->bucket_limit + 1;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
24
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
25 #if (NGX_SUPPRESS_WARN)
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
26 best = 0;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
27 #endif
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
28
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
29 for (size = 1; size < hash->max_size; size++) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
30
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
31 buckets = 0;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
32
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
33 for (i = 0; i < size; i++) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
34 test[i] = 0;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
35 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
36
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
37 for (n = (ngx_str_t *) names;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
38 n->len;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
39 n = (ngx_str_t *) ((char *) n + hash->bucket_size))
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
40 {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
41 key = 0;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
42
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
43 for (i = 0; i < n->len; i++) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
44 key += ngx_tolower(n->data[i]);
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
45 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
46
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
47 key %= size;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
48
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
49 if (test[key] == hash->bucket_limit) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
50 break;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
51 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
52
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
53 test[key]++;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
54
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
55 if (buckets < test[key]) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
56 buckets = test[key];
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
57 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
58 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
59
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
60 if (n->len == 0) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
61 if (min_buckets > buckets) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
62 min_buckets = buckets;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
63 best = size;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
64 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
65
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
66 if (hash->bucket_limit == 1) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
67 break;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
68 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
69 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
70 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
71
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
72 if (min_buckets == hash->bucket_limit + 1) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
73 ngx_log_error(NGX_LOG_EMERG, pool->log, 0,
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
74 "could not build the %s hash, you should increase "
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
75 "either %s_size: %i or %s_bucket_limit: %i",
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
76 hash->name, hash->name, hash->max_size,
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
77 hash->name, hash->bucket_limit);
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
78 ngx_free(test);
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
79 return NGX_ERROR;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
80 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
81
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
82 hash->buckets = ngx_pcalloc(pool, best * hash->bucket_size);
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
83 if (hash->buckets == NULL) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
84 ngx_free(test);
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
85 return NGX_ERROR;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
86 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
87
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
88 if (hash->bucket_limit != 1) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
89
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
90 for (i = 0; i < best; i++) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
91 test[i] = 0;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
92 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
93
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
94 for (n = (ngx_str_t *) names;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
95 n->len;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
96 n = (ngx_str_t *) ((char *) n + hash->bucket_size))
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
97 {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
98 key = 0;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
99
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
100 for (i = 0; i < n->len; i++) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
101 key += ngx_tolower(n->data[i]);
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
102 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
103
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
104 key %= best;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
105
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
106 test[key]++;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
107 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
108
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
109 for (i = 0; i < best; i++) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
110 if (test[i] == 0) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
111 continue;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
112 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
113
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
114 bucket = ngx_palloc(pool, test[i] * hash->bucket_size);
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
115 if (bucket == NULL) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
116 ngx_free(test);
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
117 return NGX_ERROR;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
118 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
119
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
120 hash->buckets[i] = bucket;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
121 bucket->len = 0;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
122 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
123 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
124
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
125 for (n = (ngx_str_t *) names;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
126 n->len;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
127 n = (ngx_str_t *) ((char *) n + hash->bucket_size))
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
128 {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
129 key = 0;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
130
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
131 for (i = 0; i < n->len; i++) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
132 key += ngx_tolower(n->data[i]);
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
133 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
134
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
135 key %= best;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
136
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
137 if (hash->bucket_limit == 1) {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
138 p = (u_char *) hash->buckets + key * hash->bucket_size;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
139 ngx_memcpy(p, n, hash->bucket_size);
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
140 continue;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
141 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
142
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
143 for (bucket = hash->buckets[key];
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
144 bucket->len;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
145 bucket = (ngx_str_t *) ((char *) bucket + hash->bucket_size))
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
146 {
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
147 bucket->len &= 0x7fffffff;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
148 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
149
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
150 ngx_memcpy(bucket, n, hash->bucket_size);
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
151 bucket->len |= 0x80000000;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
152 }
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
153
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
154 ngx_free(test);
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
155
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
156 hash->hash_size = best;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
157 hash->min_buckets = min_buckets;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
158
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
159 return NGX_OK;
3050baa54a26 nginx 0.1.28
Igor Sysoev <http://sysoev.ru>
parents:
diff changeset
160 }