hash.c 5.2 KB

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