Back to index

lightning-sunbird  0.9+nobinonly
hash.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #ifdef DEBUG
00038 static const char CVS_ID[] = "@(#) $RCSfile: hash.c,v $ $Revision: 1.3 $ $Date: 2005/01/20 02:25:45 $";
00039 #endif /* DEBUG */
00040 
00041 /*
00042  * hash.c
00043  *
00044  * This is merely a couple wrappers around NSPR's PLHashTable, using
00045  * the identity hash and arena-aware allocators.  The reason I did
00046  * this is that hash tables are used in a few places throughout the
00047  * NSS Cryptoki Framework in a fairly stereotyped way, and this allows
00048  * me to pull the commonalities into one place.  Should we ever want
00049  * to change the implementation, it's all right here.
00050  */
00051 
00052 #ifndef CK_T
00053 #include "ck.h"
00054 #endif /* CK_T */
00055 
00056 /*
00057  * nssCKFWHash
00058  *
00059  *  nssCKFWHash_Create
00060  *  nssCKFWHash_Destroy
00061  *  nssCKFWHash_Add
00062  *  nssCKFWHash_Remove
00063  *  nssCKFWHash_Count
00064  *  nssCKFWHash_Exists
00065  *  nssCKFWHash_Lookup
00066  *  nssCKFWHash_Iterate
00067  */
00068 
00069 struct nssCKFWHashStr {
00070   NSSCKFWMutex *mutex;
00071 
00072   /*
00073    * The invariant that mutex protects is:
00074    *   The count accurately reflects the hashtable state.
00075    */
00076 
00077   PLHashTable *plHashTable;
00078   CK_ULONG count;
00079 };
00080 
00081 static PLHashNumber
00082 nss_ckfw_identity_hash
00083 (
00084   const void *key
00085 )
00086 {
00087   PRUint32 i = (PRUint32)key;
00088   PR_ASSERT(sizeof(PLHashNumber) == sizeof(PRUint32));
00089   return (PLHashNumber)i;
00090 }
00091 
00092 /*
00093  * nssCKFWHash_Create
00094  *
00095  */
00096 NSS_IMPLEMENT nssCKFWHash *
00097 nssCKFWHash_Create
00098 (
00099   NSSCKFWInstance *fwInstance,
00100   NSSArena *arena,
00101   CK_RV *pError
00102 )
00103 {
00104   nssCKFWHash *rv;
00105 
00106 #ifdef NSSDEBUG
00107   if( (CK_RV *)NULL == pError ) {
00108     return (nssCKFWHash *)NULL;
00109   }
00110 
00111   if( PR_SUCCESS != nssArena_verifyPointer(arena) ) {
00112     *pError = CKR_ARGUMENTS_BAD;
00113     return (nssCKFWHash *)NULL;
00114   }
00115 #endif /* NSSDEBUG */
00116 
00117   rv = nss_ZNEW(arena, nssCKFWHash);
00118   if( (nssCKFWHash *)NULL == rv ) {
00119     *pError = CKR_HOST_MEMORY;
00120     return (nssCKFWHash *)NULL;
00121   }
00122 
00123   rv->mutex = nssCKFWInstance_CreateMutex(fwInstance, arena, pError);
00124   if( (NSSCKFWMutex *)NULL == rv->mutex ) {
00125     if( CKR_OK == *pError ) {
00126       *pError = CKR_GENERAL_ERROR;
00127     }
00128     return (nssCKFWHash *)NULL;
00129   }
00130 
00131   rv->plHashTable = PL_NewHashTable(0, nss_ckfw_identity_hash, 
00132     PL_CompareValues, PL_CompareValues, &nssArenaHashAllocOps, arena);
00133   if( (PLHashTable *)NULL == rv->plHashTable ) {
00134     (void)nssCKFWMutex_Destroy(rv->mutex);
00135     (void)nss_ZFreeIf(rv);
00136     *pError = CKR_HOST_MEMORY;
00137     return (nssCKFWHash *)NULL;
00138   }
00139 
00140   rv->count = 0;
00141 
00142   return rv;
00143 }
00144 
00145 /*
00146  * nssCKFWHash_Destroy
00147  *
00148  */
00149 NSS_IMPLEMENT void
00150 nssCKFWHash_Destroy
00151 (
00152   nssCKFWHash *hash
00153 )
00154 {
00155   (void)nssCKFWMutex_Destroy(hash->mutex);
00156   PL_HashTableDestroy(hash->plHashTable);
00157   (void)nss_ZFreeIf(hash);
00158 }
00159 
00160 /*
00161  * nssCKFWHash_Add
00162  *
00163  */
00164 NSS_IMPLEMENT CK_RV
00165 nssCKFWHash_Add
00166 (
00167   nssCKFWHash *hash,
00168   const void *key,
00169   const void *value
00170 )
00171 {
00172   CK_RV error = CKR_OK;
00173   PLHashEntry *he;
00174 
00175   error = nssCKFWMutex_Lock(hash->mutex);
00176   if( CKR_OK != error ) {
00177     return error;
00178   }
00179   
00180   he = PL_HashTableAdd(hash->plHashTable, key, (void *)value);
00181   if( (PLHashEntry *)NULL == he ) {
00182     error = CKR_HOST_MEMORY;
00183   } else {
00184     hash->count++;
00185   }
00186 
00187   (void)nssCKFWMutex_Unlock(hash->mutex);
00188 
00189   return error;
00190 }
00191 
00192 /*
00193  * nssCKFWHash_Remove
00194  *
00195  */
00196 NSS_IMPLEMENT void
00197 nssCKFWHash_Remove
00198 (
00199   nssCKFWHash *hash,
00200   const void *it
00201 )
00202 {
00203   PRBool found;
00204 
00205   if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
00206     return;
00207   }
00208 
00209   found = PL_HashTableRemove(hash->plHashTable, it);
00210   if( found ) {
00211     hash->count--;
00212   }
00213 
00214   (void)nssCKFWMutex_Unlock(hash->mutex);
00215   return;
00216 }
00217 
00218 /*
00219  * nssCKFWHash_Count
00220  *
00221  */
00222 NSS_IMPLEMENT CK_ULONG
00223 nssCKFWHash_Count
00224 (
00225   nssCKFWHash *hash
00226 )
00227 {
00228   CK_ULONG count;
00229 
00230   if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
00231     return (CK_ULONG)0;
00232   }
00233 
00234   count = hash->count;
00235 
00236   (void)nssCKFWMutex_Unlock(hash->mutex);
00237 
00238   return count;
00239 }
00240 
00241 /*
00242  * nssCKFWHash_Exists
00243  *
00244  */
00245 NSS_IMPLEMENT CK_BBOOL
00246 nssCKFWHash_Exists
00247 (
00248   nssCKFWHash *hash,
00249   const void *it
00250 )
00251 {
00252   void *value;
00253 
00254   if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
00255     return CK_FALSE;
00256   }
00257 
00258   value = PL_HashTableLookup(hash->plHashTable, it);
00259 
00260   (void)nssCKFWMutex_Unlock(hash->mutex);
00261 
00262   if( (void *)NULL == value ) {
00263     return CK_FALSE;
00264   } else {
00265     return CK_TRUE;
00266   }
00267 }
00268 
00269 /*
00270  * nssCKFWHash_Lookup
00271  *
00272  */
00273 NSS_IMPLEMENT void *
00274 nssCKFWHash_Lookup
00275 (
00276   nssCKFWHash *hash,
00277   const void *it
00278 )
00279 {
00280   void *rv;
00281 
00282   if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
00283     return (void *)NULL;
00284   }
00285 
00286   rv = PL_HashTableLookup(hash->plHashTable, it);
00287 
00288   (void)nssCKFWMutex_Unlock(hash->mutex);
00289 
00290   return rv;
00291 }
00292 
00293 struct arg_str {
00294   nssCKFWHashIterator fcn;
00295   void *closure;
00296 };
00297 
00298 static PRIntn
00299 nss_ckfwhash_enumerator
00300 (
00301   PLHashEntry *he,
00302   PRIntn index,
00303   void *arg
00304 )
00305 {
00306   struct arg_str *as = (struct arg_str *)arg;
00307   as->fcn(he->key, he->value, as->closure);
00308   return HT_ENUMERATE_NEXT;
00309 }
00310 
00311 /*
00312  * nssCKFWHash_Iterate
00313  *
00314  * NOTE that the iteration function will be called with the hashtable locked.
00315  */
00316 NSS_IMPLEMENT void
00317 nssCKFWHash_Iterate
00318 (
00319   nssCKFWHash *hash,
00320   nssCKFWHashIterator fcn,
00321   void *closure
00322 )
00323 {
00324   struct arg_str as;
00325   as.fcn = fcn;
00326   as.closure = closure;
00327 
00328   if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
00329     return;
00330   }
00331 
00332   PL_HashTableEnumerateEntries(hash->plHashTable, nss_ckfwhash_enumerator, &as);
00333 
00334   (void)nssCKFWMutex_Unlock(hash->mutex);
00335 
00336   return;
00337 }