This source file includes following definitions.
- zend_accel_hash_clean
- zend_accel_hash_init
- zend_accel_hash_update
- zend_accel_hash_find_ex
- zend_accel_hash_find
- zend_accel_hash_find_entry
- zend_accel_hash_str_find
- zend_accel_hash_str_find_entry
- zend_accel_hash_unlink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include "ZendAccelerator.h"
23 #include "zend_accelerator_hash.h"
24 #include "zend_hash.h"
25 #include "zend_shared_alloc.h"
26
27
28 static uint prime_numbers[] =
29 {5, 11, 19, 53, 107, 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987, 262237, 524521, 1048793 };
30 static uint num_prime_numbers = sizeof(prime_numbers) / sizeof(uint);
31
32 void zend_accel_hash_clean(zend_accel_hash *accel_hash)
33 {
34 accel_hash->num_entries = 0;
35 accel_hash->num_direct_entries = 0;
36 memset(accel_hash->hash_table, 0, sizeof(zend_accel_hash_entry *)*accel_hash->max_num_entries);
37 }
38
39 void zend_accel_hash_init(zend_accel_hash *accel_hash, uint32_t hash_size)
40 {
41 uint i;
42
43 for (i=0; i<num_prime_numbers; i++) {
44 if (hash_size <= prime_numbers[i]) {
45 hash_size = prime_numbers[i];
46 break;
47 }
48 }
49
50 accel_hash->num_entries = 0;
51 accel_hash->num_direct_entries = 0;
52 accel_hash->max_num_entries = hash_size;
53
54
55 accel_hash->hash_table = zend_shared_alloc(sizeof(zend_accel_hash_entry *)*accel_hash->max_num_entries);
56 if (!accel_hash->hash_table) {
57 zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
58 return;
59 }
60
61
62 accel_hash->hash_entries = zend_shared_alloc(sizeof(zend_accel_hash_entry)*accel_hash->max_num_entries);
63 if (!accel_hash->hash_entries) {
64 zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
65 return;
66 }
67 memset(accel_hash->hash_table, 0, sizeof(zend_accel_hash_entry *)*accel_hash->max_num_entries);
68 }
69
70
71
72
73
74 zend_accel_hash_entry* zend_accel_hash_update(zend_accel_hash *accel_hash, char *key, uint32_t key_length, zend_bool indirect, void *data)
75 {
76 zend_ulong hash_value;
77 zend_ulong index;
78 zend_accel_hash_entry *entry;
79 zend_accel_hash_entry *indirect_bucket = NULL;
80
81 if (indirect) {
82 indirect_bucket = (zend_accel_hash_entry*)data;
83 while (indirect_bucket->indirect) {
84 indirect_bucket = (zend_accel_hash_entry*)indirect_bucket->data;
85 }
86 }
87
88 hash_value = zend_inline_hash_func(key, key_length);
89 index = hash_value % accel_hash->max_num_entries;
90
91
92 entry = accel_hash->hash_table[index];
93 while (entry) {
94 if (entry->hash_value == hash_value
95 && entry->key_length == key_length
96 && !memcmp(entry->key, key, key_length)) {
97
98 if (entry->indirect) {
99 if (indirect_bucket) {
100 entry->data = indirect_bucket;
101 } else {
102 ((zend_accel_hash_entry*)entry->data)->data = data;
103 }
104 } else {
105 if (indirect_bucket) {
106 accel_hash->num_direct_entries--;
107 entry->data = indirect_bucket;
108 entry->indirect = 1;
109 } else {
110 entry->data = data;
111 }
112 }
113 return entry;
114 }
115 entry = entry->next;
116 }
117
118
119 if (accel_hash->num_entries == accel_hash->max_num_entries) {
120 return NULL;
121 }
122
123 entry = &accel_hash->hash_entries[accel_hash->num_entries++];
124 if (indirect) {
125 entry->data = indirect_bucket;
126 entry->indirect = 1;
127 } else {
128 accel_hash->num_direct_entries++;
129 entry->data = data;
130 entry->indirect = 0;
131 }
132 entry->hash_value = hash_value;
133 entry->key = key;
134 entry->key_length = key_length;
135 entry->next = accel_hash->hash_table[index];
136 accel_hash->hash_table[index] = entry;
137 return entry;
138 }
139
140 static zend_always_inline void* zend_accel_hash_find_ex(zend_accel_hash *accel_hash, char *key, uint32_t key_length, zend_ulong hash_value, int data)
141 {
142 zend_ulong index = hash_value % accel_hash->max_num_entries;
143 zend_accel_hash_entry *entry = accel_hash->hash_table[index];
144
145 while (entry) {
146 if (entry->hash_value == hash_value
147 && entry->key_length == key_length
148 && !memcmp(entry->key, key, key_length)) {
149 if (entry->indirect) {
150 if (data) {
151 return ((zend_accel_hash_entry*)entry->data)->data;
152 } else {
153 return entry->data;
154 }
155 } else {
156 if (data) {
157 return entry->data;
158 } else {
159 return entry;
160 }
161 }
162 }
163 entry = entry->next;
164 }
165 return NULL;
166 }
167
168
169
170
171 void* zend_accel_hash_find(zend_accel_hash *accel_hash, zend_string *key)
172 {
173 return zend_accel_hash_find_ex(
174 accel_hash,
175 ZSTR_VAL(key),
176 ZSTR_LEN(key),
177 zend_string_hash_val(key),
178 1);
179 }
180
181
182
183
184 zend_accel_hash_entry* zend_accel_hash_find_entry(zend_accel_hash *accel_hash, zend_string *key)
185 {
186 return (zend_accel_hash_entry *)zend_accel_hash_find_ex(
187 accel_hash,
188 ZSTR_VAL(key),
189 ZSTR_LEN(key),
190 zend_string_hash_val(key),
191 0);
192 }
193
194
195
196
197 void* zend_accel_hash_str_find(zend_accel_hash *accel_hash, char *key, uint32_t key_length)
198 {
199 return zend_accel_hash_find_ex(
200 accel_hash,
201 key,
202 key_length,
203 zend_inline_hash_func(key, key_length),
204 1);
205 }
206
207
208
209
210 zend_accel_hash_entry* zend_accel_hash_str_find_entry(zend_accel_hash *accel_hash, char *key, uint32_t key_length)
211 {
212 return (zend_accel_hash_entry *)zend_accel_hash_find_ex(
213 accel_hash,
214 key,
215 key_length,
216 zend_inline_hash_func(key, key_length),
217 0);
218 }
219
220 int zend_accel_hash_unlink(zend_accel_hash *accel_hash, char *key, uint32_t key_length)
221 {
222 zend_ulong hash_value;
223 zend_ulong index;
224 zend_accel_hash_entry *entry, *last_entry=NULL;
225
226 hash_value = zend_inline_hash_func(key, key_length);
227 index = hash_value % accel_hash->max_num_entries;
228
229 entry = accel_hash->hash_table[index];
230 while (entry) {
231 if (entry->hash_value == hash_value
232 && entry->key_length == key_length
233 && !memcmp(entry->key, key, key_length)) {
234 if (!entry->indirect) {
235 accel_hash->num_direct_entries--;
236 }
237 if (last_entry) {
238 last_entry->next = entry->next;
239 } else {
240 accel_hash->hash_table[index] = entry->next;
241 }
242 return SUCCESS;
243 }
244 last_entry = entry;
245 entry = entry->next;
246 }
247 return FAILURE;
248 }