| OLD | NEW |
| (Empty) | |
| 1 /* ***** BEGIN LICENSE BLOCK ***** |
| 2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 3 * |
| 4 * The contents of this file are subject to the Mozilla Public License Version |
| 5 * 1.1 (the "License"); you may not use this file except in compliance with |
| 6 * the License. You may obtain a copy of the License at |
| 7 * http://www.mozilla.org/MPL/ |
| 8 * |
| 9 * Software distributed under the License is distributed on an "AS IS" basis, |
| 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 11 * for the specific language governing rights and limitations under the |
| 12 * License. |
| 13 * |
| 14 * The Original Code is the Netscape security libraries. |
| 15 * |
| 16 * The Initial Developer of the Original Code is |
| 17 * Netscape Communications Corporation. |
| 18 * Portions created by the Initial Developer are Copyright (C) 1994-2000 |
| 19 * the Initial Developer. All Rights Reserved. |
| 20 * |
| 21 * Contributor(s): |
| 22 * |
| 23 * Alternatively, the contents of this file may be used under the terms of |
| 24 * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 26 * in which case the provisions of the GPL or the LGPL are applicable instead |
| 27 * of those above. If you wish to allow use of your version of this file only |
| 28 * under the terms of either the GPL or the LGPL, and not to allow others to |
| 29 * use your version of this file under the terms of the MPL, indicate your |
| 30 * decision by deleting the provisions above and replace them with the notice |
| 31 * and other provisions required by the GPL or the LGPL. If you do not delete |
| 32 * the provisions above, a recipient may use your version of this file under |
| 33 * the terms of any one of the MPL, the GPL or the LGPL. |
| 34 * |
| 35 * ***** END LICENSE BLOCK ***** */ |
| 36 |
| 37 #ifdef DEBUG |
| 38 static const char CVS_ID[] = "@(#) $RCSfile: hash.c,v $ $Revision: 1.4 $ $Date:
2009/02/09 07:55:52 $"; |
| 39 #endif /* DEBUG */ |
| 40 |
| 41 /* |
| 42 * hash.c |
| 43 * |
| 44 * This is merely a couple wrappers around NSPR's PLHashTable, using |
| 45 * the identity hash and arena-aware allocators. The reason I did |
| 46 * this is that hash tables are used in a few places throughout the |
| 47 * NSS Cryptoki Framework in a fairly stereotyped way, and this allows |
| 48 * me to pull the commonalities into one place. Should we ever want |
| 49 * to change the implementation, it's all right here. |
| 50 */ |
| 51 |
| 52 #ifndef CK_T |
| 53 #include "ck.h" |
| 54 #endif /* CK_T */ |
| 55 |
| 56 /* |
| 57 * nssCKFWHash |
| 58 * |
| 59 * nssCKFWHash_Create |
| 60 * nssCKFWHash_Destroy |
| 61 * nssCKFWHash_Add |
| 62 * nssCKFWHash_Remove |
| 63 * nssCKFWHash_Count |
| 64 * nssCKFWHash_Exists |
| 65 * nssCKFWHash_Lookup |
| 66 * nssCKFWHash_Iterate |
| 67 */ |
| 68 |
| 69 struct nssCKFWHashStr { |
| 70 NSSCKFWMutex *mutex; |
| 71 |
| 72 /* |
| 73 * The invariant that mutex protects is: |
| 74 * The count accurately reflects the hashtable state. |
| 75 */ |
| 76 |
| 77 PLHashTable *plHashTable; |
| 78 CK_ULONG count; |
| 79 }; |
| 80 |
| 81 static PLHashNumber |
| 82 nss_ckfw_identity_hash |
| 83 ( |
| 84 const void *key |
| 85 ) |
| 86 { |
| 87 PRUint32 i = (PRUint32)key; |
| 88 PR_ASSERT(sizeof(PLHashNumber) == sizeof(PRUint32)); |
| 89 return (PLHashNumber)i; |
| 90 } |
| 91 |
| 92 /* |
| 93 * nssCKFWHash_Create |
| 94 * |
| 95 */ |
| 96 NSS_IMPLEMENT nssCKFWHash * |
| 97 nssCKFWHash_Create |
| 98 ( |
| 99 NSSCKFWInstance *fwInstance, |
| 100 NSSArena *arena, |
| 101 CK_RV *pError |
| 102 ) |
| 103 { |
| 104 nssCKFWHash *rv; |
| 105 |
| 106 #ifdef NSSDEBUG |
| 107 if (!pError) { |
| 108 return (nssCKFWHash *)NULL; |
| 109 } |
| 110 |
| 111 if( PR_SUCCESS != nssArena_verifyPointer(arena) ) { |
| 112 *pError = CKR_ARGUMENTS_BAD; |
| 113 return (nssCKFWHash *)NULL; |
| 114 } |
| 115 #endif /* NSSDEBUG */ |
| 116 |
| 117 rv = nss_ZNEW(arena, nssCKFWHash); |
| 118 if (!rv) { |
| 119 *pError = CKR_HOST_MEMORY; |
| 120 return (nssCKFWHash *)NULL; |
| 121 } |
| 122 |
| 123 rv->mutex = nssCKFWInstance_CreateMutex(fwInstance, arena, pError); |
| 124 if (!rv->mutex) { |
| 125 if( CKR_OK == *pError ) { |
| 126 *pError = CKR_GENERAL_ERROR; |
| 127 } |
| 128 return (nssCKFWHash *)NULL; |
| 129 } |
| 130 |
| 131 rv->plHashTable = PL_NewHashTable(0, nss_ckfw_identity_hash, |
| 132 PL_CompareValues, PL_CompareValues, &nssArenaHashAllocOps, arena); |
| 133 if (!rv->plHashTable) { |
| 134 (void)nssCKFWMutex_Destroy(rv->mutex); |
| 135 (void)nss_ZFreeIf(rv); |
| 136 *pError = CKR_HOST_MEMORY; |
| 137 return (nssCKFWHash *)NULL; |
| 138 } |
| 139 |
| 140 rv->count = 0; |
| 141 |
| 142 return rv; |
| 143 } |
| 144 |
| 145 /* |
| 146 * nssCKFWHash_Destroy |
| 147 * |
| 148 */ |
| 149 NSS_IMPLEMENT void |
| 150 nssCKFWHash_Destroy |
| 151 ( |
| 152 nssCKFWHash *hash |
| 153 ) |
| 154 { |
| 155 (void)nssCKFWMutex_Destroy(hash->mutex); |
| 156 PL_HashTableDestroy(hash->plHashTable); |
| 157 (void)nss_ZFreeIf(hash); |
| 158 } |
| 159 |
| 160 /* |
| 161 * nssCKFWHash_Add |
| 162 * |
| 163 */ |
| 164 NSS_IMPLEMENT CK_RV |
| 165 nssCKFWHash_Add |
| 166 ( |
| 167 nssCKFWHash *hash, |
| 168 const void *key, |
| 169 const void *value |
| 170 ) |
| 171 { |
| 172 CK_RV error = CKR_OK; |
| 173 PLHashEntry *he; |
| 174 |
| 175 error = nssCKFWMutex_Lock(hash->mutex); |
| 176 if( CKR_OK != error ) { |
| 177 return error; |
| 178 } |
| 179 |
| 180 he = PL_HashTableAdd(hash->plHashTable, key, (void *)value); |
| 181 if (!he) { |
| 182 error = CKR_HOST_MEMORY; |
| 183 } else { |
| 184 hash->count++; |
| 185 } |
| 186 |
| 187 (void)nssCKFWMutex_Unlock(hash->mutex); |
| 188 |
| 189 return error; |
| 190 } |
| 191 |
| 192 /* |
| 193 * nssCKFWHash_Remove |
| 194 * |
| 195 */ |
| 196 NSS_IMPLEMENT void |
| 197 nssCKFWHash_Remove |
| 198 ( |
| 199 nssCKFWHash *hash, |
| 200 const void *it |
| 201 ) |
| 202 { |
| 203 PRBool found; |
| 204 |
| 205 if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) { |
| 206 return; |
| 207 } |
| 208 |
| 209 found = PL_HashTableRemove(hash->plHashTable, it); |
| 210 if( found ) { |
| 211 hash->count--; |
| 212 } |
| 213 |
| 214 (void)nssCKFWMutex_Unlock(hash->mutex); |
| 215 return; |
| 216 } |
| 217 |
| 218 /* |
| 219 * nssCKFWHash_Count |
| 220 * |
| 221 */ |
| 222 NSS_IMPLEMENT CK_ULONG |
| 223 nssCKFWHash_Count |
| 224 ( |
| 225 nssCKFWHash *hash |
| 226 ) |
| 227 { |
| 228 CK_ULONG count; |
| 229 |
| 230 if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) { |
| 231 return (CK_ULONG)0; |
| 232 } |
| 233 |
| 234 count = hash->count; |
| 235 |
| 236 (void)nssCKFWMutex_Unlock(hash->mutex); |
| 237 |
| 238 return count; |
| 239 } |
| 240 |
| 241 /* |
| 242 * nssCKFWHash_Exists |
| 243 * |
| 244 */ |
| 245 NSS_IMPLEMENT CK_BBOOL |
| 246 nssCKFWHash_Exists |
| 247 ( |
| 248 nssCKFWHash *hash, |
| 249 const void *it |
| 250 ) |
| 251 { |
| 252 void *value; |
| 253 |
| 254 if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) { |
| 255 return CK_FALSE; |
| 256 } |
| 257 |
| 258 value = PL_HashTableLookup(hash->plHashTable, it); |
| 259 |
| 260 (void)nssCKFWMutex_Unlock(hash->mutex); |
| 261 |
| 262 if (!value) { |
| 263 return CK_FALSE; |
| 264 } else { |
| 265 return CK_TRUE; |
| 266 } |
| 267 } |
| 268 |
| 269 /* |
| 270 * nssCKFWHash_Lookup |
| 271 * |
| 272 */ |
| 273 NSS_IMPLEMENT void * |
| 274 nssCKFWHash_Lookup |
| 275 ( |
| 276 nssCKFWHash *hash, |
| 277 const void *it |
| 278 ) |
| 279 { |
| 280 void *rv; |
| 281 |
| 282 if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) { |
| 283 return (void *)NULL; |
| 284 } |
| 285 |
| 286 rv = PL_HashTableLookup(hash->plHashTable, it); |
| 287 |
| 288 (void)nssCKFWMutex_Unlock(hash->mutex); |
| 289 |
| 290 return rv; |
| 291 } |
| 292 |
| 293 struct arg_str { |
| 294 nssCKFWHashIterator fcn; |
| 295 void *closure; |
| 296 }; |
| 297 |
| 298 static PRIntn |
| 299 nss_ckfwhash_enumerator |
| 300 ( |
| 301 PLHashEntry *he, |
| 302 PRIntn index, |
| 303 void *arg |
| 304 ) |
| 305 { |
| 306 struct arg_str *as = (struct arg_str *)arg; |
| 307 as->fcn(he->key, he->value, as->closure); |
| 308 return HT_ENUMERATE_NEXT; |
| 309 } |
| 310 |
| 311 /* |
| 312 * nssCKFWHash_Iterate |
| 313 * |
| 314 * NOTE that the iteration function will be called with the hashtable locked. |
| 315 */ |
| 316 NSS_IMPLEMENT void |
| 317 nssCKFWHash_Iterate |
| 318 ( |
| 319 nssCKFWHash *hash, |
| 320 nssCKFWHashIterator fcn, |
| 321 void *closure |
| 322 ) |
| 323 { |
| 324 struct arg_str as; |
| 325 as.fcn = fcn; |
| 326 as.closure = closure; |
| 327 |
| 328 if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) { |
| 329 return; |
| 330 } |
| 331 |
| 332 PL_HashTableEnumerateEntries(hash->plHashTable, nss_ckfwhash_enumerator, &as); |
| 333 |
| 334 (void)nssCKFWMutex_Unlock(hash->mutex); |
| 335 |
| 336 return; |
| 337 } |
| OLD | NEW |