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