When doing cert traversals, create the certs in full as they are found. This avoids thrashing the softoken's object cache when the database has a large number of certs.

This commit is contained in:
ian.mcgreer%sun.com 2002-04-26 14:34:05 +00:00
Родитель 1378739a27
Коммит cdae9ed5a1
5 изменённых файлов: 186 добавлений и 23 удалений

Просмотреть файл

@ -41,7 +41,7 @@
*/
#ifdef DEBUG
static const char DEV_CVS_ID[] = "@(#) $RCSfile: dev.h,v $ $Revision: 1.25 $ $Date: 2002/04/19 23:06:39 $ $Name: $";
static const char DEV_CVS_ID[] = "@(#) $RCSfile: dev.h,v $ $Revision: 1.26 $ $Date: 2002/04/26 14:33:59 $ $Name: $";
#endif /* DEBUG */
#ifndef NSSCKT_H
@ -952,6 +952,16 @@ nssToken_NofifyCertsNotVisible
NSSToken *tok
);
NSS_EXTERN PRStatus
nssToken_TraverseCertificates
(
NSSToken *token,
nssSession *sessionOpt,
nssTokenSearchType searchType,
PRStatus (* callback)(nssCryptokiObject *instance, void *arg),
void *arg
);
#endif
PR_END_EXTERN_C

Просмотреть файл

@ -32,7 +32,7 @@
*/
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: devtoken.c,v $ $Revision: 1.20 $ $Date: 2002/04/25 20:49:49 $ $Name: $";
static const char CVS_ID[] = "@(#) $RCSfile: devtoken.c,v $ $Revision: 1.21 $ $Date: 2002/04/26 14:33:59 $ $Name: $";
#endif /* DEBUG */
#ifndef NSSCKEPV_H
@ -1547,3 +1547,113 @@ nssToken_IsPresent
return nssSlot_IsTokenPresent(token->slot);
}
/* Sigh. The methods to find objects declared above cause problems with
* the low-level object cache in the softoken -- the objects are found in
* toto, then one wave of GetAttributes is done, then another. Having a
* large number of objects causes the cache to be thrashed, as the objects
* are gone before there's any chance to ask for their attributes.
* So, for now, bringing back traversal methods for certs. This way all of
* the cert's attributes can be grabbed immediately after finding it,
* increasing the likelihood that the cache takes care of it.
*/
NSS_IMPLEMENT PRStatus
nssToken_TraverseCertificates
(
NSSToken *token,
nssSession *sessionOpt,
nssTokenSearchType searchType,
PRStatus (* callback)(nssCryptokiObject *instance, void *arg),
void *arg
)
{
CK_RV ckrv;
CK_ULONG count;
CK_OBJECT_HANDLE *objectHandles;
CK_ATTRIBUTE_PTR attr;
CK_ATTRIBUTE cert_template[2];
CK_ULONG ctsize;
NSSArena *arena;
PRStatus status;
PRUint32 arraySize, numHandles;
nssCryptokiObject **objects;
void *epv = nssToken_GetCryptokiEPV(token);
nssSession *session = (sessionOpt) ? sessionOpt : token->defaultSession;
/* template for all certs */
NSS_CK_TEMPLATE_START(cert_template, attr, ctsize);
if (searchType == nssTokenSearchType_SessionOnly) {
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
} else if (searchType == nssTokenSearchType_TokenOnly ||
searchType == nssTokenSearchType_TokenForced) {
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
}
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize);
/* the arena is only for the array of object handles */
arena = nssArena_Create();
if (!arena) {
return PR_FAILURE;
}
arraySize = OBJECT_STACK_SIZE;
numHandles = 0;
objectHandles = nss_ZNEWARRAY(arena, CK_OBJECT_HANDLE, arraySize);
if (!objectHandles) {
goto loser;
}
nssSession_EnterMonitor(session); /* ==== session lock === */
/* Initialize the find with the template */
ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle,
cert_template, ctsize);
if (ckrv != CKR_OK) {
nssSession_ExitMonitor(session);
goto loser;
}
while (PR_TRUE) {
/* Issue the find for up to arraySize - numHandles objects */
ckrv = CKAPI(epv)->C_FindObjects(session->handle,
objectHandles + numHandles,
arraySize - numHandles,
&count);
if (ckrv != CKR_OK) {
nssSession_ExitMonitor(session);
goto loser;
}
/* bump the number of found objects */
numHandles += count;
if (numHandles < arraySize) {
break;
}
/* the array is filled, double it and continue */
arraySize *= 2;
objectHandles = nss_ZREALLOCARRAY(objectHandles,
CK_OBJECT_HANDLE,
arraySize);
if (!objectHandles) {
nssSession_ExitMonitor(session);
goto loser;
}
}
ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle);
nssSession_ExitMonitor(session); /* ==== end session lock === */
if (ckrv != CKR_OK) {
goto loser;
}
if (numHandles > 0) {
objects = create_objects_from_handles(token, session,
objectHandles, numHandles);
if (objects) {
nssCryptokiObject **op;
for (op = objects; *op; op++) {
status = (*callback)(*op, arg);
}
nss_ZFreeIf(objects);
}
}
nssArena_Destroy(arena);
return PR_SUCCESS;
loser:
nssArena_Destroy(arena);
return PR_FAILURE;
}

Просмотреть файл

@ -32,7 +32,7 @@
*/
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: pkibase.c,v $ $Revision: 1.4 $ $Date: 2002/04/18 19:26:17 $ $Name: $";
static const char CVS_ID[] = "@(#) $RCSfile: pkibase.c,v $ $Revision: 1.5 $ $Date: 2002/04/26 14:34:04 $ $Name: $";
#endif /* DEBUG */
#ifndef DEV_H
@ -716,7 +716,7 @@ find_object_in_collection
return (pkiObjectCollectionNode *)NULL;
}
static PRStatus
static pkiObjectCollectionNode *
add_object_instance
(
nssPKIObjectCollection *collection,
@ -740,7 +740,7 @@ add_object_instance
* are not using it, it must be destroyed.
*/
nssCryptokiObject_Destroy(instance);
return PR_SUCCESS;
return node;
}
mark = nssArena_Mark(collection->arena);
if (!mark) {
@ -780,13 +780,13 @@ add_object_instance
status = PR_SUCCESS;
}
nssArena_Unmark(collection->arena, mark);
return status;
return node;
loser:
if (mark) {
nssArena_Release(collection->arena, mark);
}
nssCryptokiObject_Destroy(instance);
return PR_FAILURE;
return (pkiObjectCollectionNode *)NULL;
}
NSS_IMPLEMENT PRStatus
@ -799,13 +799,14 @@ nssPKIObjectCollection_AddInstances
{
PRStatus status = PR_SUCCESS;
PRUint32 i = 0;
pkiObjectCollectionNode *node;
if (instances) {
for (; *instances; instances++, i++) {
if (numInstances > 0 && i == numInstances) {
break;
}
status = add_object_instance(collection, *instances);
if (status != PR_SUCCESS) {
node = add_object_instance(collection, *instances);
if (node == NULL) {
goto loser;
}
}
@ -891,6 +892,35 @@ nssPKIObjectCollection_Traverse
return PR_SUCCESS;
}
NSS_IMPLEMENT PRStatus
nssPKIObjectCollection_AddInstanceAsObject
(
nssPKIObjectCollection *collection,
nssCryptokiObject *instance
)
{
pkiObjectCollectionNode *node;
node = add_object_instance(collection, instance);
if (node == NULL) {
return PR_FAILURE;
}
if (!node->haveObject) {
node->object = (*collection->createObject)(node->object);
node->haveObject = PR_TRUE;
}
#ifdef NSS_3_4_CODE
else {
/* The instance was added to a pre-existing node. This
* function is *only* being used for certificates, and having
* multiple instances of certs in 3.X requires updating the
* CERTCertificate.
*/
STAN_ForceCERTCertificateUpdate((NSSCertificate *)node->object);
}
#endif
return PR_SUCCESS;
}
/*
* Certificate collections
*/

Просмотреть файл

@ -35,7 +35,7 @@
#define PKIM_H
#ifdef DEBUG
static const char PKIM_CVS_ID[] = "@(#) $RCSfile: pkim.h,v $ $Revision: 1.19 $ $Date: 2002/04/19 23:06:43 $ $Name: $";
static const char PKIM_CVS_ID[] = "@(#) $RCSfile: pkim.h,v $ $Revision: 1.20 $ $Date: 2002/04/26 14:34:04 $ $Name: $";
#endif /* DEBUG */
#ifndef BASE_H
@ -496,6 +496,18 @@ nssPKIObjectCollection_Traverse
nssPKIObjectCallback *callback
);
/* This function is being added for NSS 3.5. It corresponds to the function
* nssToken_TraverseCertificates. The idea is to use the collection during
* a traversal, creating certs each time a new instance is added for which
* a cert does not already exist.
*/
NSS_EXTERN PRStatus
nssPKIObjectCollection_AddInstanceAsObject
(
nssPKIObjectCollection *collection,
nssCryptokiObject *instance
);
/* nssPKIObjectCollection_GetCertificates
*
* Get all of the certificates in the collection.

Просмотреть файл

@ -32,7 +32,7 @@
*/
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: trustdomain.c,v $ $Revision: 1.41 $ $Date: 2002/04/22 19:09:01 $ $Name: $";
static const char CVS_ID[] = "@(#) $RCSfile: trustdomain.c,v $ $Revision: 1.42 $ $Date: 2002/04/26 14:34:05 $ $Name: $";
#endif /* DEBUG */
#ifndef DEV_H
@ -1035,6 +1035,13 @@ NSSTrustDomain_FindUserCertificatesForEmailSigning
return NULL;
}
static PRStatus
collector(nssCryptokiObject *instance, void *arg)
{
nssPKIObjectCollection *collection = (nssPKIObjectCollection *)arg;
return nssPKIObjectCollection_AddInstanceAsObject(collection, instance);
}
NSS_IMPLEMENT PRStatus *
NSSTrustDomain_TraverseCertificates
(
@ -1052,6 +1059,7 @@ NSSTrustDomain_TraverseCertificates
nssUpdateLevel updateLevel;
NSSCertificate **cached = NULL;
nssList *certList;
certList = nssList_Create(NULL, PR_FALSE);
if (!certList) return NULL;
(void *)nssTrustDomain_GetCertsFromCache(td, certList);
@ -1073,7 +1081,6 @@ NSSTrustDomain_TraverseCertificates
token = nssSlot_GetToken(*slotp);
if (token) {
nssSession *session;
nssCryptokiObject **instances;
nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
/* get a session for the token */
session = nssTrustDomain_GetSessionForToken(td, token);
@ -1082,21 +1089,15 @@ NSSTrustDomain_TraverseCertificates
goto loser;
}
/* perform the traversal */
instances = nssToken_FindCertificates(token,
session,
tokenOnly,
0, &status);
status = nssToken_TraverseCertificates(token,
session,
tokenOnly,
collector,
collection);
nssToken_Destroy(token);
if (status != PR_SUCCESS) {
goto loser;
}
/* add the found certificates to the collection */
status = nssPKIObjectCollection_AddInstances(collection,
instances, 0);
nss_ZFreeIf(instances);
if (status != PR_SUCCESS) {
goto loser;
}
}
}