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