/security/nss/lib/ckfw/hash.c

http://github.com/zpao/v8monkey · C · 338 lines · 196 code · 48 blank · 94 comment · 26 complexity · 41660172c2989fc5cc0b9ce3290baec2 MD5 · raw file

  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. #ifdef DEBUG
  37. static const char CVS_ID[] = "@(#) $RCSfile: hash.c,v $ $Revision: 1.5 $ $Date: 2010/09/09 21:14:24 $";
  38. #endif /* DEBUG */
  39. /*
  40. * hash.c
  41. *
  42. * This is merely a couple wrappers around NSPR's PLHashTable, using
  43. * the identity hash and arena-aware allocators. The reason I did
  44. * this is that hash tables are used in a few places throughout the
  45. * NSS Cryptoki Framework in a fairly stereotyped way, and this allows
  46. * me to pull the commonalities into one place. Should we ever want
  47. * to change the implementation, it's all right here.
  48. */
  49. #ifndef CK_T
  50. #include "ck.h"
  51. #endif /* CK_T */
  52. /*
  53. * nssCKFWHash
  54. *
  55. * nssCKFWHash_Create
  56. * nssCKFWHash_Destroy
  57. * nssCKFWHash_Add
  58. * nssCKFWHash_Remove
  59. * nssCKFWHash_Count
  60. * nssCKFWHash_Exists
  61. * nssCKFWHash_Lookup
  62. * nssCKFWHash_Iterate
  63. */
  64. struct nssCKFWHashStr {
  65. NSSCKFWMutex *mutex;
  66. /*
  67. * The invariant that mutex protects is:
  68. * The count accurately reflects the hashtable state.
  69. */
  70. PLHashTable *plHashTable;
  71. CK_ULONG count;
  72. };
  73. static PLHashNumber
  74. nss_ckfw_identity_hash
  75. (
  76. const void *key
  77. )
  78. {
  79. PRUint32 i = (PRUint32)key;
  80. PR_ASSERT(sizeof(PLHashNumber) == sizeof(PRUint32));
  81. return (PLHashNumber)i;
  82. }
  83. /*
  84. * nssCKFWHash_Create
  85. *
  86. */
  87. NSS_IMPLEMENT nssCKFWHash *
  88. nssCKFWHash_Create
  89. (
  90. NSSCKFWInstance *fwInstance,
  91. NSSArena *arena,
  92. CK_RV *pError
  93. )
  94. {
  95. nssCKFWHash *rv;
  96. #ifdef NSSDEBUG
  97. if (!pError) {
  98. return (nssCKFWHash *)NULL;
  99. }
  100. if( PR_SUCCESS != nssArena_verifyPointer(arena) ) {
  101. *pError = CKR_ARGUMENTS_BAD;
  102. return (nssCKFWHash *)NULL;
  103. }
  104. #endif /* NSSDEBUG */
  105. rv = nss_ZNEW(arena, nssCKFWHash);
  106. if (!rv) {
  107. *pError = CKR_HOST_MEMORY;
  108. return (nssCKFWHash *)NULL;
  109. }
  110. rv->mutex = nssCKFWInstance_CreateMutex(fwInstance, arena, pError);
  111. if (!rv->mutex) {
  112. if( CKR_OK == *pError ) {
  113. (void)nss_ZFreeIf(rv);
  114. *pError = CKR_GENERAL_ERROR;
  115. }
  116. return (nssCKFWHash *)NULL;
  117. }
  118. rv->plHashTable = PL_NewHashTable(0, nss_ckfw_identity_hash,
  119. PL_CompareValues, PL_CompareValues, &nssArenaHashAllocOps, arena);
  120. if (!rv->plHashTable) {
  121. (void)nssCKFWMutex_Destroy(rv->mutex);
  122. (void)nss_ZFreeIf(rv);
  123. *pError = CKR_HOST_MEMORY;
  124. return (nssCKFWHash *)NULL;
  125. }
  126. rv->count = 0;
  127. return rv;
  128. }
  129. /*
  130. * nssCKFWHash_Destroy
  131. *
  132. */
  133. NSS_IMPLEMENT void
  134. nssCKFWHash_Destroy
  135. (
  136. nssCKFWHash *hash
  137. )
  138. {
  139. (void)nssCKFWMutex_Destroy(hash->mutex);
  140. PL_HashTableDestroy(hash->plHashTable);
  141. (void)nss_ZFreeIf(hash);
  142. }
  143. /*
  144. * nssCKFWHash_Add
  145. *
  146. */
  147. NSS_IMPLEMENT CK_RV
  148. nssCKFWHash_Add
  149. (
  150. nssCKFWHash *hash,
  151. const void *key,
  152. const void *value
  153. )
  154. {
  155. CK_RV error = CKR_OK;
  156. PLHashEntry *he;
  157. error = nssCKFWMutex_Lock(hash->mutex);
  158. if( CKR_OK != error ) {
  159. return error;
  160. }
  161. he = PL_HashTableAdd(hash->plHashTable, key, (void *)value);
  162. if (!he) {
  163. error = CKR_HOST_MEMORY;
  164. } else {
  165. hash->count++;
  166. }
  167. (void)nssCKFWMutex_Unlock(hash->mutex);
  168. return error;
  169. }
  170. /*
  171. * nssCKFWHash_Remove
  172. *
  173. */
  174. NSS_IMPLEMENT void
  175. nssCKFWHash_Remove
  176. (
  177. nssCKFWHash *hash,
  178. const void *it
  179. )
  180. {
  181. PRBool found;
  182. if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
  183. return;
  184. }
  185. found = PL_HashTableRemove(hash->plHashTable, it);
  186. if( found ) {
  187. hash->count--;
  188. }
  189. (void)nssCKFWMutex_Unlock(hash->mutex);
  190. return;
  191. }
  192. /*
  193. * nssCKFWHash_Count
  194. *
  195. */
  196. NSS_IMPLEMENT CK_ULONG
  197. nssCKFWHash_Count
  198. (
  199. nssCKFWHash *hash
  200. )
  201. {
  202. CK_ULONG count;
  203. if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
  204. return (CK_ULONG)0;
  205. }
  206. count = hash->count;
  207. (void)nssCKFWMutex_Unlock(hash->mutex);
  208. return count;
  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. if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
  223. return CK_FALSE;
  224. }
  225. value = PL_HashTableLookup(hash->plHashTable, it);
  226. (void)nssCKFWMutex_Unlock(hash->mutex);
  227. if (!value) {
  228. return CK_FALSE;
  229. } else {
  230. return CK_TRUE;
  231. }
  232. }
  233. /*
  234. * nssCKFWHash_Lookup
  235. *
  236. */
  237. NSS_IMPLEMENT void *
  238. nssCKFWHash_Lookup
  239. (
  240. nssCKFWHash *hash,
  241. const void *it
  242. )
  243. {
  244. void *rv;
  245. if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
  246. return (void *)NULL;
  247. }
  248. rv = PL_HashTableLookup(hash->plHashTable, it);
  249. (void)nssCKFWMutex_Unlock(hash->mutex);
  250. return rv;
  251. }
  252. struct arg_str {
  253. nssCKFWHashIterator fcn;
  254. void *closure;
  255. };
  256. static PRIntn
  257. nss_ckfwhash_enumerator
  258. (
  259. PLHashEntry *he,
  260. PRIntn index,
  261. void *arg
  262. )
  263. {
  264. struct arg_str *as = (struct arg_str *)arg;
  265. as->fcn(he->key, he->value, as->closure);
  266. return HT_ENUMERATE_NEXT;
  267. }
  268. /*
  269. * nssCKFWHash_Iterate
  270. *
  271. * NOTE that the iteration function will be called with the hashtable locked.
  272. */
  273. NSS_IMPLEMENT void
  274. nssCKFWHash_Iterate
  275. (
  276. nssCKFWHash *hash,
  277. nssCKFWHashIterator fcn,
  278. void *closure
  279. )
  280. {
  281. struct arg_str as;
  282. as.fcn = fcn;
  283. as.closure = closure;
  284. if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
  285. return;
  286. }
  287. PL_HashTableEnumerateEntries(hash->plHashTable, nss_ckfwhash_enumerator, &as);
  288. (void)nssCKFWMutex_Unlock(hash->mutex);
  289. return;
  290. }