| 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 * pkix_pl_hashtable.c | |
| 6 * | |
| 7 * Hashtable Object Functions | |
| 8 * | |
| 9 */ | |
| 10 | |
| 11 #include "pkix_pl_hashtable.h" | |
| 12 | |
| 13 /* --Private-Structure-------------------------------------------- */ | |
| 14 | |
| 15 struct PKIX_PL_HashTableStruct { | |
| 16 pkix_pl_PrimHashTable *primHash; | |
| 17 PKIX_PL_Mutex *tableLock; | |
| 18 PKIX_UInt32 maxEntriesPerBucket; | |
| 19 }; | |
| 20 | |
| 21 /* --Private-Functions-------------------------------------------- */ | |
| 22 | |
| 23 #define PKIX_MUTEX_UNLOCK(mutex) \ | |
| 24 do { \ | |
| 25 if (mutex && lockedMutex == (PKIX_PL_Mutex *)(mutex)) { \ | |
| 26 pkixTempResult = \ | |
| 27 PKIX_PL_Mutex_Unlock((mutex), plContext); \ | |
| 28 PORT_Assert(pkixTempResult == NULL); \ | |
| 29 if (pkixTempResult) { \ | |
| 30 PKIX_DoAddError(&stdVars, pkixTempResult, plContext); \ | |
| 31 pkixTempResult = NULL; \ | |
| 32 } \ | |
| 33 lockedMutex = NULL; \ | |
| 34 } else { \ | |
| 35 PORT_Assert(lockedMutex == NULL); \ | |
| 36 }\ | |
| 37 } while (0) | |
| 38 | |
| 39 | |
| 40 #define PKIX_MUTEX_LOCK(mutex) \ | |
| 41 do { \ | |
| 42 if (mutex){ \ | |
| 43 PORT_Assert(lockedMutex == NULL); \ | |
| 44 PKIX_CHECK(PKIX_PL_Mutex_Lock((mutex), plContext), \ | |
| 45 PKIX_MUTEXLOCKFAILED); \ | |
| 46 lockedMutex = (mutex); \ | |
| 47 } \ | |
| 48 } while (0) | |
| 49 | |
| 50 /* | |
| 51 * FUNCTION: pkix_pl_HashTable_Destroy | |
| 52 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) | |
| 53 */ | |
| 54 static PKIX_Error * | |
| 55 pkix_pl_HashTable_Destroy( | |
| 56 PKIX_PL_Object *object, | |
| 57 void *plContext) | |
| 58 { | |
| 59 PKIX_PL_HashTable *ht = NULL; | |
| 60 pkix_pl_HT_Elem *item = NULL; | |
| 61 PKIX_UInt32 i; | |
| 62 | |
| 63 PKIX_ENTER(HASHTABLE, "pkix_pl_HashTable_Destroy"); | |
| 64 PKIX_NULLCHECK_ONE(object); | |
| 65 | |
| 66 PKIX_CHECK(pkix_CheckType(object, PKIX_HASHTABLE_TYPE, plContext), | |
| 67 PKIX_OBJECTNOTHASHTABLE); | |
| 68 | |
| 69 ht = (PKIX_PL_HashTable*) object; | |
| 70 | |
| 71 /* DecRef every object in the primitive hash table */ | |
| 72 for (i = 0; i < ht->primHash->size; i++) { | |
| 73 for (item = ht->primHash->buckets[i]; | |
| 74 item != NULL; | |
| 75 item = item->next) { | |
| 76 PKIX_DECREF(item->key); | |
| 77 PKIX_DECREF(item->value); | |
| 78 } | |
| 79 } | |
| 80 | |
| 81 PKIX_CHECK(pkix_pl_PrimHashTable_Destroy(ht->primHash, plContext), | |
| 82 PKIX_PRIMHASHTABLEDESTROYFAILED); | |
| 83 | |
| 84 PKIX_DECREF(ht->tableLock); | |
| 85 | |
| 86 cleanup: | |
| 87 | |
| 88 PKIX_RETURN(HASHTABLE); | |
| 89 } | |
| 90 | |
| 91 /* | |
| 92 * FUNCTION: pkix_pl_HashTable_RegisterSelf | |
| 93 * DESCRIPTION: | |
| 94 * Registers PKIX_HASHTABLE_TYPE and its related functions with systemClasses[] | |
| 95 * THREAD SAFETY: | |
| 96 * Not Thread Safe - for performance and complexity reasons | |
| 97 * | |
| 98 * Since this function is only called by PKIX_PL_Initialize, which should | |
| 99 * only be called once, it is acceptable that this function is not | |
| 100 * thread-safe. | |
| 101 */ | |
| 102 PKIX_Error * | |
| 103 pkix_pl_HashTable_RegisterSelf( | |
| 104 void *plContext) | |
| 105 { | |
| 106 | |
| 107 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; | |
| 108 pkix_ClassTable_Entry entry; | |
| 109 | |
| 110 PKIX_ENTER(HASHTABLE, "pkix_pl_HashTable_RegisterSelf"); | |
| 111 | |
| 112 entry.description = "HashTable"; | |
| 113 entry.objCounter = 0; | |
| 114 entry.typeObjectSize = sizeof(PKIX_PL_HashTable); | |
| 115 entry.destructor = pkix_pl_HashTable_Destroy; | |
| 116 entry.equalsFunction = NULL; | |
| 117 entry.hashcodeFunction = NULL; | |
| 118 entry.toStringFunction = NULL; | |
| 119 entry.comparator = NULL; | |
| 120 entry.duplicateFunction = NULL; | |
| 121 | |
| 122 systemClasses[PKIX_HASHTABLE_TYPE] = entry; | |
| 123 | |
| 124 PKIX_RETURN(HASHTABLE); | |
| 125 } | |
| 126 | |
| 127 /* --Public-Functions------------------------------------------------------- */ | |
| 128 | |
| 129 /* | |
| 130 * FUNCTION: PKIX_PL_HashTable_Create (see comments in pkix_pl_system.h) | |
| 131 */ | |
| 132 PKIX_Error * | |
| 133 PKIX_PL_HashTable_Create( | |
| 134 PKIX_UInt32 numBuckets, | |
| 135 PKIX_UInt32 maxEntriesPerBucket, | |
| 136 PKIX_PL_HashTable **pResult, | |
| 137 void *plContext) | |
| 138 { | |
| 139 PKIX_PL_HashTable *hashTable = NULL; | |
| 140 | |
| 141 PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Create"); | |
| 142 PKIX_NULLCHECK_ONE(pResult); | |
| 143 | |
| 144 if (numBuckets == 0) { | |
| 145 PKIX_ERROR(PKIX_NUMBUCKETSEQUALSZERO); | |
| 146 } | |
| 147 | |
| 148 /* Allocate a new hashtable */ | |
| 149 PKIX_CHECK(PKIX_PL_Object_Alloc | |
| 150 (PKIX_HASHTABLE_TYPE, | |
| 151 sizeof (PKIX_PL_HashTable), | |
| 152 (PKIX_PL_Object **)&hashTable, | |
| 153 plContext), | |
| 154 PKIX_COULDNOTCREATEHASHTABLEOBJECT); | |
| 155 | |
| 156 /* Create the underlying primitive hash table type */ | |
| 157 PKIX_CHECK(pkix_pl_PrimHashTable_Create | |
| 158 (numBuckets, &hashTable->primHash, plContext), | |
| 159 PKIX_PRIMHASHTABLECREATEFAILED); | |
| 160 | |
| 161 /* Create a lock for this table */ | |
| 162 PKIX_CHECK(PKIX_PL_Mutex_Create(&hashTable->tableLock, plContext), | |
| 163 PKIX_ERRORCREATINGTABLELOCK); | |
| 164 | |
| 165 hashTable->maxEntriesPerBucket = maxEntriesPerBucket; | |
| 166 | |
| 167 *pResult = hashTable; | |
| 168 | |
| 169 cleanup: | |
| 170 | |
| 171 if (PKIX_ERROR_RECEIVED){ | |
| 172 PKIX_DECREF(hashTable); | |
| 173 } | |
| 174 | |
| 175 PKIX_RETURN(HASHTABLE); | |
| 176 } | |
| 177 | |
| 178 /* | |
| 179 * FUNCTION: PKIX_PL_HashTable_Add (see comments in pkix_pl_system.h) | |
| 180 */ | |
| 181 PKIX_Error * | |
| 182 PKIX_PL_HashTable_Add( | |
| 183 PKIX_PL_HashTable *ht, | |
| 184 PKIX_PL_Object *key, | |
| 185 PKIX_PL_Object *value, | |
| 186 void *plContext) | |
| 187 { | |
| 188 PKIX_PL_Mutex *lockedMutex = NULL; | |
| 189 PKIX_PL_Object *deletedKey = NULL; | |
| 190 PKIX_PL_Object *deletedValue = NULL; | |
| 191 PKIX_UInt32 hashCode; | |
| 192 PKIX_PL_EqualsCallback keyComp; | |
| 193 PKIX_UInt32 bucketSize = 0; | |
| 194 | |
| 195 PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Add"); | |
| 196 | |
| 197 #if !defined(PKIX_OBJECT_LEAK_TEST) | |
| 198 PKIX_NULLCHECK_THREE(ht, key, value); | |
| 199 #else | |
| 200 PKIX_NULLCHECK_TWO(key, value); | |
| 201 | |
| 202 if (ht == NULL) { | |
| 203 PKIX_RETURN(HASHTABLE); | |
| 204 } | |
| 205 #endif | |
| 206 /* Insert into primitive hashtable */ | |
| 207 | |
| 208 PKIX_CHECK(PKIX_PL_Object_Hashcode(key, &hashCode, plContext), | |
| 209 PKIX_OBJECTHASHCODEFAILED); | |
| 210 | |
| 211 PKIX_CHECK(pkix_pl_Object_RetrieveEqualsCallback | |
| 212 (key, &keyComp, plContext), | |
| 213 PKIX_OBJECTRETRIEVEEQUALSCALLBACKFAILED); | |
| 214 | |
| 215 PKIX_MUTEX_LOCK(ht->tableLock); | |
| 216 | |
| 217 PKIX_CHECK(pkix_pl_PrimHashTable_GetBucketSize | |
| 218 (ht->primHash, | |
| 219 hashCode, | |
| 220 &bucketSize, | |
| 221 plContext), | |
| 222 PKIX_PRIMHASHTABLEGETBUCKETSIZEFAILED); | |
| 223 | |
| 224 if (ht->maxEntriesPerBucket != 0 && | |
| 225 bucketSize >= ht->maxEntriesPerBucket) { | |
| 226 /* drop the last one in the bucket */ | |
| 227 PKIX_CHECK(pkix_pl_PrimHashTable_RemoveFIFO | |
| 228 (ht->primHash, | |
| 229 hashCode, | |
| 230 (void **) &deletedKey, | |
| 231 (void **) &deletedValue, | |
| 232 plContext), | |
| 233 PKIX_PRIMHASHTABLEGETBUCKETSIZEFAILED); | |
| 234 PKIX_DECREF(deletedKey); | |
| 235 PKIX_DECREF(deletedValue); | |
| 236 } | |
| 237 | |
| 238 PKIX_CHECK(pkix_pl_PrimHashTable_Add | |
| 239 (ht->primHash, | |
| 240 (void *)key, | |
| 241 (void *)value, | |
| 242 hashCode, | |
| 243 keyComp, | |
| 244 plContext), | |
| 245 PKIX_PRIMHASHTABLEADDFAILED); | |
| 246 | |
| 247 PKIX_INCREF(key); | |
| 248 PKIX_INCREF(value); | |
| 249 PKIX_MUTEX_UNLOCK(ht->tableLock); | |
| 250 | |
| 251 /* | |
| 252 * we don't call PKIX_PL_InvalidateCache here b/c we have | |
| 253 * not implemented toString or hashcode for this Object | |
| 254 */ | |
| 255 | |
| 256 cleanup: | |
| 257 | |
| 258 PKIX_MUTEX_UNLOCK(ht->tableLock); | |
| 259 | |
| 260 PKIX_RETURN(HASHTABLE); | |
| 261 } | |
| 262 | |
| 263 /* | |
| 264 * FUNCTION: PKIX_PL_HashTable_Remove (see comments in pkix_pl_system.h) | |
| 265 */ | |
| 266 PKIX_Error * | |
| 267 PKIX_PL_HashTable_Remove( | |
| 268 PKIX_PL_HashTable *ht, | |
| 269 PKIX_PL_Object *key, | |
| 270 void *plContext) | |
| 271 { | |
| 272 PKIX_PL_Mutex *lockedMutex = NULL; | |
| 273 PKIX_PL_Object *origKey = NULL; | |
| 274 PKIX_PL_Object *value = NULL; | |
| 275 PKIX_UInt32 hashCode; | |
| 276 PKIX_PL_EqualsCallback keyComp; | |
| 277 | |
| 278 PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Remove"); | |
| 279 | |
| 280 #if !defined(PKIX_OBJECT_LEAK_TEST) | |
| 281 PKIX_NULLCHECK_TWO(ht, key); | |
| 282 #else | |
| 283 PKIX_NULLCHECK_ONE(key); | |
| 284 | |
| 285 if (ht == NULL) { | |
| 286 PKIX_RETURN(HASHTABLE); | |
| 287 } | |
| 288 #endif | |
| 289 | |
| 290 PKIX_CHECK(PKIX_PL_Object_Hashcode(key, &hashCode, plContext), | |
| 291 PKIX_OBJECTHASHCODEFAILED); | |
| 292 | |
| 293 PKIX_CHECK(pkix_pl_Object_RetrieveEqualsCallback | |
| 294 (key, &keyComp, plContext), | |
| 295 PKIX_OBJECTRETRIEVEEQUALSCALLBACKFAILED); | |
| 296 | |
| 297 PKIX_MUTEX_LOCK(ht->tableLock); | |
| 298 | |
| 299 /* Remove from primitive hashtable */ | |
| 300 PKIX_CHECK(pkix_pl_PrimHashTable_Remove | |
| 301 (ht->primHash, | |
| 302 (void *)key, | |
| 303 hashCode, | |
| 304 keyComp, | |
| 305 (void **)&origKey, | |
| 306 (void **)&value, | |
| 307 plContext), | |
| 308 PKIX_PRIMHASHTABLEREMOVEFAILED); | |
| 309 | |
| 310 PKIX_MUTEX_UNLOCK(ht->tableLock); | |
| 311 | |
| 312 PKIX_DECREF(origKey); | |
| 313 PKIX_DECREF(value); | |
| 314 | |
| 315 /* | |
| 316 * we don't call PKIX_PL_InvalidateCache here b/c we have | |
| 317 * not implemented toString or hashcode for this Object | |
| 318 */ | |
| 319 | |
| 320 cleanup: | |
| 321 | |
| 322 PKIX_MUTEX_UNLOCK(ht->tableLock); | |
| 323 | |
| 324 PKIX_RETURN(HASHTABLE); | |
| 325 } | |
| 326 | |
| 327 /* | |
| 328 * FUNCTION: PKIX_PL_HashTable_Lookup (see comments in pkix_pl_system.h) | |
| 329 */ | |
| 330 PKIX_Error * | |
| 331 PKIX_PL_HashTable_Lookup( | |
| 332 PKIX_PL_HashTable *ht, | |
| 333 PKIX_PL_Object *key, | |
| 334 PKIX_PL_Object **pResult, | |
| 335 void *plContext) | |
| 336 { | |
| 337 PKIX_PL_Mutex *lockedMutex = NULL; | |
| 338 PKIX_UInt32 hashCode; | |
| 339 PKIX_PL_EqualsCallback keyComp; | |
| 340 PKIX_PL_Object *result = NULL; | |
| 341 | |
| 342 PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Lookup"); | |
| 343 | |
| 344 #if !defined(PKIX_OBJECT_LEAK_TEST) | |
| 345 PKIX_NULLCHECK_THREE(ht, key, pResult); | |
| 346 #else | |
| 347 PKIX_NULLCHECK_TWO(key, pResult); | |
| 348 | |
| 349 if (ht == NULL) { | |
| 350 PKIX_RETURN(HASHTABLE); | |
| 351 } | |
| 352 #endif | |
| 353 | |
| 354 PKIX_CHECK(PKIX_PL_Object_Hashcode(key, &hashCode, plContext), | |
| 355 PKIX_OBJECTHASHCODEFAILED); | |
| 356 | |
| 357 PKIX_CHECK(pkix_pl_Object_RetrieveEqualsCallback | |
| 358 (key, &keyComp, plContext), | |
| 359 PKIX_OBJECTRETRIEVEEQUALSCALLBACKFAILED); | |
| 360 | |
| 361 PKIX_MUTEX_LOCK(ht->tableLock); | |
| 362 | |
| 363 /* Lookup in primitive hashtable */ | |
| 364 PKIX_CHECK(pkix_pl_PrimHashTable_Lookup | |
| 365 (ht->primHash, | |
| 366 (void *)key, | |
| 367 hashCode, | |
| 368 keyComp, | |
| 369 (void **)&result, | |
| 370 plContext), | |
| 371 PKIX_PRIMHASHTABLELOOKUPFAILED); | |
| 372 | |
| 373 PKIX_INCREF(result); | |
| 374 PKIX_MUTEX_UNLOCK(ht->tableLock); | |
| 375 | |
| 376 *pResult = result; | |
| 377 | |
| 378 cleanup: | |
| 379 | |
| 380 PKIX_MUTEX_UNLOCK(ht->tableLock); | |
| 381 | |
| 382 PKIX_RETURN(HASHTABLE); | |
| 383 } | |
| OLD | NEW |