| 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 |