OLD | NEW |
| (Empty) |
1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
4 | |
5 /* | |
6 * hash.c | |
7 * | |
8 * This is merely a couple wrappers around NSPR's PLHashTable, using | |
9 * the identity hash and arena-aware allocators. The reason I did | |
10 * this is that hash tables are used in a few places throughout the | |
11 * NSS Cryptoki Framework in a fairly stereotyped way, and this allows | |
12 * me to pull the commonalities into one place. Should we ever want | |
13 * to change the implementation, it's all right here. | |
14 */ | |
15 | |
16 #ifndef CK_T | |
17 #include "ck.h" | |
18 #endif /* CK_T */ | |
19 | |
20 /* | |
21 * nssCKFWHash | |
22 * | |
23 * nssCKFWHash_Create | |
24 * nssCKFWHash_Destroy | |
25 * nssCKFWHash_Add | |
26 * nssCKFWHash_Remove | |
27 * nssCKFWHash_Count | |
28 * nssCKFWHash_Exists | |
29 * nssCKFWHash_Lookup | |
30 * nssCKFWHash_Iterate | |
31 */ | |
32 | |
33 struct nssCKFWHashStr { | |
34 NSSCKFWMutex *mutex; | |
35 | |
36 /* | |
37 * The invariant that mutex protects is: | |
38 * The count accurately reflects the hashtable state. | |
39 */ | |
40 | |
41 PLHashTable *plHashTable; | |
42 CK_ULONG count; | |
43 }; | |
44 | |
45 static PLHashNumber | |
46 nss_ckfw_identity_hash( | |
47 const void *key) | |
48 { | |
49 return (PLHashNumber)((char *)key - (char *)NULL); | |
50 } | |
51 | |
52 /* | |
53 * nssCKFWHash_Create | |
54 * | |
55 */ | |
56 NSS_IMPLEMENT nssCKFWHash * | |
57 nssCKFWHash_Create( | |
58 NSSCKFWInstance *fwInstance, | |
59 NSSArena *arena, | |
60 CK_RV *pError) | |
61 { | |
62 nssCKFWHash *rv; | |
63 | |
64 #ifdef NSSDEBUG | |
65 if (!pError) { | |
66 return (nssCKFWHash *)NULL; | |
67 } | |
68 | |
69 if (PR_SUCCESS != nssArena_verifyPointer(arena)) { | |
70 *pError = CKR_ARGUMENTS_BAD; | |
71 return (nssCKFWHash *)NULL; | |
72 } | |
73 #endif /* NSSDEBUG */ | |
74 | |
75 rv = nss_ZNEW(arena, nssCKFWHash); | |
76 if (!rv) { | |
77 *pError = CKR_HOST_MEMORY; | |
78 return (nssCKFWHash *)NULL; | |
79 } | |
80 | |
81 rv->mutex = nssCKFWInstance_CreateMutex(fwInstance, arena, pError); | |
82 if (!rv->mutex) { | |
83 if (CKR_OK == *pError) { | |
84 *pError = CKR_GENERAL_ERROR; | |
85 } | |
86 (void)nss_ZFreeIf(rv); | |
87 return (nssCKFWHash *)NULL; | |
88 } | |
89 | |
90 rv->plHashTable = PL_NewHashTable(0, nss_ckfw_identity_hash, | |
91 PL_CompareValues, PL_CompareValues, &nssAr
enaHashAllocOps, arena); | |
92 if (!rv->plHashTable) { | |
93 (void)nssCKFWMutex_Destroy(rv->mutex); | |
94 (void)nss_ZFreeIf(rv); | |
95 *pError = CKR_HOST_MEMORY; | |
96 return (nssCKFWHash *)NULL; | |
97 } | |
98 | |
99 rv->count = 0; | |
100 | |
101 return rv; | |
102 } | |
103 | |
104 /* | |
105 * nssCKFWHash_Destroy | |
106 * | |
107 */ | |
108 NSS_IMPLEMENT void | |
109 nssCKFWHash_Destroy( | |
110 nssCKFWHash *hash) | |
111 { | |
112 (void)nssCKFWMutex_Destroy(hash->mutex); | |
113 PL_HashTableDestroy(hash->plHashTable); | |
114 (void)nss_ZFreeIf(hash); | |
115 } | |
116 | |
117 /* | |
118 * nssCKFWHash_Add | |
119 * | |
120 */ | |
121 NSS_IMPLEMENT CK_RV | |
122 nssCKFWHash_Add( | |
123 nssCKFWHash *hash, | |
124 const void *key, | |
125 const void *value) | |
126 { | |
127 CK_RV error = CKR_OK; | |
128 PLHashEntry *he; | |
129 | |
130 error = nssCKFWMutex_Lock(hash->mutex); | |
131 if (CKR_OK != error) { | |
132 return error; | |
133 } | |
134 | |
135 he = PL_HashTableAdd(hash->plHashTable, key, (void *)value); | |
136 if (!he) { | |
137 error = CKR_HOST_MEMORY; | |
138 } else { | |
139 hash->count++; | |
140 } | |
141 | |
142 (void)nssCKFWMutex_Unlock(hash->mutex); | |
143 | |
144 return error; | |
145 } | |
146 | |
147 /* | |
148 * nssCKFWHash_Remove | |
149 * | |
150 */ | |
151 NSS_IMPLEMENT void | |
152 nssCKFWHash_Remove( | |
153 nssCKFWHash *hash, | |
154 const void *it) | |
155 { | |
156 PRBool found; | |
157 | |
158 if (CKR_OK != nssCKFWMutex_Lock(hash->mutex)) { | |
159 return; | |
160 } | |
161 | |
162 found = PL_HashTableRemove(hash->plHashTable, it); | |
163 if (found) { | |
164 hash->count--; | |
165 } | |
166 | |
167 (void)nssCKFWMutex_Unlock(hash->mutex); | |
168 return; | |
169 } | |
170 | |
171 /* | |
172 * nssCKFWHash_Count | |
173 * | |
174 */ | |
175 NSS_IMPLEMENT CK_ULONG | |
176 nssCKFWHash_Count( | |
177 nssCKFWHash *hash) | |
178 { | |
179 CK_ULONG count; | |
180 | |
181 if (CKR_OK != nssCKFWMutex_Lock(hash->mutex)) { | |
182 return (CK_ULONG)0; | |
183 } | |
184 | |
185 count = hash->count; | |
186 | |
187 (void)nssCKFWMutex_Unlock(hash->mutex); | |
188 | |
189 return count; | |
190 } | |
191 | |
192 /* | |
193 * nssCKFWHash_Exists | |
194 * | |
195 */ | |
196 NSS_IMPLEMENT CK_BBOOL | |
197 nssCKFWHash_Exists( | |
198 nssCKFWHash *hash, | |
199 const void *it) | |
200 { | |
201 void *value; | |
202 | |
203 if (CKR_OK != nssCKFWMutex_Lock(hash->mutex)) { | |
204 return CK_FALSE; | |
205 } | |
206 | |
207 value = PL_HashTableLookup(hash->plHashTable, it); | |
208 | |
209 (void)nssCKFWMutex_Unlock(hash->mutex); | |
210 | |
211 if (!value) { | |
212 return CK_FALSE; | |
213 } else { | |
214 return CK_TRUE; | |
215 } | |
216 } | |
217 | |
218 /* | |
219 * nssCKFWHash_Lookup | |
220 * | |
221 */ | |
222 NSS_IMPLEMENT void * | |
223 nssCKFWHash_Lookup( | |
224 nssCKFWHash *hash, | |
225 const void *it) | |
226 { | |
227 void *rv; | |
228 | |
229 if (CKR_OK != nssCKFWMutex_Lock(hash->mutex)) { | |
230 return (void *)NULL; | |
231 } | |
232 | |
233 rv = PL_HashTableLookup(hash->plHashTable, it); | |
234 | |
235 (void)nssCKFWMutex_Unlock(hash->mutex); | |
236 | |
237 return rv; | |
238 } | |
239 | |
240 struct arg_str { | |
241 nssCKFWHashIterator fcn; | |
242 void *closure; | |
243 }; | |
244 | |
245 static PRIntn | |
246 nss_ckfwhash_enumerator( | |
247 PLHashEntry *he, | |
248 PRIntn index, | |
249 void *arg) | |
250 { | |
251 struct arg_str *as = (struct arg_str *)arg; | |
252 as->fcn(he->key, he->value, as->closure); | |
253 return HT_ENUMERATE_NEXT; | |
254 } | |
255 | |
256 /* | |
257 * nssCKFWHash_Iterate | |
258 * | |
259 * NOTE that the iteration function will be called with the hashtable locked. | |
260 */ | |
261 NSS_IMPLEMENT void | |
262 nssCKFWHash_Iterate( | |
263 nssCKFWHash *hash, | |
264 nssCKFWHashIterator fcn, | |
265 void *closure) | |
266 { | |
267 struct arg_str as; | |
268 as.fcn = fcn; | |
269 as.closure = closure; | |
270 | |
271 if (CKR_OK != nssCKFWMutex_Lock(hash->mutex)) { | |
272 return; | |
273 } | |
274 | |
275 PL_HashTableEnumerateEntries(hash->plHashTable, nss_ckfwhash_enumerator, &as
); | |
276 | |
277 (void)nssCKFWMutex_Unlock(hash->mutex); | |
278 | |
279 return; | |
280 } | |
OLD | NEW |