PageRenderTime 27ms CodeModel.GetById 13ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 1ms

/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
 37#ifdef DEBUG
 38static const char CVS_ID[] = "@(#) $RCSfile: hash.c,v $ $Revision: 1.5 $ $Date: 2010/09/09 21:14:24 $";
 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
 69struct 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
 81static PLHashNumber
 82nss_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 */
 96NSS_IMPLEMENT nssCKFWHash *
 97nssCKFWHash_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      (void)nss_ZFreeIf(rv);
127      *pError = CKR_GENERAL_ERROR;
128    }
129    return (nssCKFWHash *)NULL;
130  }
131
132  rv->plHashTable = PL_NewHashTable(0, nss_ckfw_identity_hash, 
133    PL_CompareValues, PL_CompareValues, &nssArenaHashAllocOps, arena);
134  if (!rv->plHashTable) {
135    (void)nssCKFWMutex_Destroy(rv->mutex);
136    (void)nss_ZFreeIf(rv);
137    *pError = CKR_HOST_MEMORY;
138    return (nssCKFWHash *)NULL;
139  }
140
141  rv->count = 0;
142
143  return rv;
144}
145
146/*
147 * nssCKFWHash_Destroy
148 *
149 */
150NSS_IMPLEMENT void
151nssCKFWHash_Destroy
152(
153  nssCKFWHash *hash
154)
155{
156  (void)nssCKFWMutex_Destroy(hash->mutex);
157  PL_HashTableDestroy(hash->plHashTable);
158  (void)nss_ZFreeIf(hash);
159}
160
161/*
162 * nssCKFWHash_Add
163 *
164 */
165NSS_IMPLEMENT CK_RV
166nssCKFWHash_Add
167(
168  nssCKFWHash *hash,
169  const void *key,
170  const void *value
171)
172{
173  CK_RV error = CKR_OK;
174  PLHashEntry *he;
175
176  error = nssCKFWMutex_Lock(hash->mutex);
177  if( CKR_OK != error ) {
178    return error;
179  }
180  
181  he = PL_HashTableAdd(hash->plHashTable, key, (void *)value);
182  if (!he) {
183    error = CKR_HOST_MEMORY;
184  } else {
185    hash->count++;
186  }
187
188  (void)nssCKFWMutex_Unlock(hash->mutex);
189
190  return error;
191}
192
193/*
194 * nssCKFWHash_Remove
195 *
196 */
197NSS_IMPLEMENT void
198nssCKFWHash_Remove
199(
200  nssCKFWHash *hash,
201  const void *it
202)
203{
204  PRBool found;
205
206  if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
207    return;
208  }
209
210  found = PL_HashTableRemove(hash->plHashTable, it);
211  if( found ) {
212    hash->count--;
213  }
214
215  (void)nssCKFWMutex_Unlock(hash->mutex);
216  return;
217}
218
219/*
220 * nssCKFWHash_Count
221 *
222 */
223NSS_IMPLEMENT CK_ULONG
224nssCKFWHash_Count
225(
226  nssCKFWHash *hash
227)
228{
229  CK_ULONG count;
230
231  if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
232    return (CK_ULONG)0;
233  }
234
235  count = hash->count;
236
237  (void)nssCKFWMutex_Unlock(hash->mutex);
238
239  return count;
240}
241
242/*
243 * nssCKFWHash_Exists
244 *
245 */
246NSS_IMPLEMENT CK_BBOOL
247nssCKFWHash_Exists
248(
249  nssCKFWHash *hash,
250  const void *it
251)
252{
253  void *value;
254
255  if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
256    return CK_FALSE;
257  }
258
259  value = PL_HashTableLookup(hash->plHashTable, it);
260
261  (void)nssCKFWMutex_Unlock(hash->mutex);
262
263  if (!value) {
264    return CK_FALSE;
265  } else {
266    return CK_TRUE;
267  }
268}
269
270/*
271 * nssCKFWHash_Lookup
272 *
273 */
274NSS_IMPLEMENT void *
275nssCKFWHash_Lookup
276(
277  nssCKFWHash *hash,
278  const void *it
279)
280{
281  void *rv;
282
283  if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
284    return (void *)NULL;
285  }
286
287  rv = PL_HashTableLookup(hash->plHashTable, it);
288
289  (void)nssCKFWMutex_Unlock(hash->mutex);
290
291  return rv;
292}
293
294struct arg_str {
295  nssCKFWHashIterator fcn;
296  void *closure;
297};
298
299static PRIntn
300nss_ckfwhash_enumerator
301(
302  PLHashEntry *he,
303  PRIntn index,
304  void *arg
305)
306{
307  struct arg_str *as = (struct arg_str *)arg;
308  as->fcn(he->key, he->value, as->closure);
309  return HT_ENUMERATE_NEXT;
310}
311
312/*
313 * nssCKFWHash_Iterate
314 *
315 * NOTE that the iteration function will be called with the hashtable locked.
316 */
317NSS_IMPLEMENT void
318nssCKFWHash_Iterate
319(
320  nssCKFWHash *hash,
321  nssCKFWHashIterator fcn,
322  void *closure
323)
324{
325  struct arg_str as;
326  as.fcn = fcn;
327  as.closure = closure;
328
329  if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
330    return;
331  }
332
333  PL_HashTableEnumerateEntries(hash->plHashTable, nss_ckfwhash_enumerator, &as);
334
335  (void)nssCKFWMutex_Unlock(hash->mutex);
336
337  return;
338}