diff options
Diffstat (limited to 'lib/libaccess/aclflush.cpp')
-rw-r--r-- | lib/libaccess/aclflush.cpp | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/lib/libaccess/aclflush.cpp b/lib/libaccess/aclflush.cpp new file mode 100644 index 00000000..dfee47d6 --- /dev/null +++ b/lib/libaccess/aclflush.cpp @@ -0,0 +1,178 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* + * Source file for the ACL_CacheFlush-related routines. + */ + +#include <base/nsassert.h> +#include <base/util.h> +#include <libaccess/acl.h> +#include "aclpriv.h" +#include <libaccess/aclproto.h> +#include <libaccess/aclglobal.h> +#include <libaccess/las.h> +#include "aclcache.h" +#include <libaccess/dbtlibaccess.h> + +extern void ACL_DatabaseDestroy(void); + +PRIntn +deletelists(PRHashEntry *he, PRIntn i, void *arg) +{ + ACLListHandle_t *acllist=(ACLListHandle_t *)he->value; + NSErr_t *errp = 0; + + NS_ASSERT(he); + NS_ASSERT(he->value); + + if (acllist->ref_count) { + // If the list is in use, increment the counter. Then set the + // stale flag. The other user can't delete the list since we're + // counted as well. Finally, decrement the counter and whoever + // sets it to zero will delete the ACL List. + NS_ASSERT(ACL_CritHeld()); + acllist->ref_count++; + acllist->flags |= ACL_LIST_STALE; + if (--acllist->ref_count == 0) + ACL_ListDestroy(errp, acllist); + } else { + ACL_ListDestroy(errp, acllist); + } + + return 0; +} + +PRIntn +restartdeletelists(PRHashEntry *he, PRIntn i, void *arg) +{ + NSErr_t *errp = 0; + + // Cannot be anyone left using the lists, so just free them no matter + // what. + ACLListHandle_t *acllist=(ACLListHandle_t *)he->value; + + NS_ASSERT(he); + NS_ASSERT(he->value); + + ACL_ListDestroy(errp, acllist); + + return 0; +} + +static AclCacheFlushFunc_t AclCacheFlushRoutine = NULL; + +NSAPI_PUBLIC int +ACL_CacheFlushRegister(AclCacheFlushFunc_t flush_func) +{ + NS_ASSERT(flush_func); + AclCacheFlushRoutine = flush_func; + + return 0; +} + +NSAPI_PUBLIC int +ACL_CacheFlush(void) +{ + ACLGlobal_p newACLGlobal; + NSErr_t *errp = 0; + + NS_ASSERT(ACLGlobal); + NS_ASSERT(ACLGlobal->masterlist); + NS_ASSERT(ACLGlobal->listhash); + NS_ASSERT(ACLGlobal->urihash); + NS_ASSERT(ACLGlobal->urigethash); + NS_ASSERT(ACLGlobal->pool); + + ACL_CritEnter(); + + // Swap the pointers. Keep using the current database/method tables + // until the new ones are built. This is a kludge. An in-progress + // evaluation could conceivably get messed up, but the window seems + // small. + newACLGlobal = oldACLGlobal; + + oldACLGlobal = ACLGlobal; + ACLGlobal = newACLGlobal; + + // Prepare the new ACLGlobal structure + ACL_UriHashInit(); /* Also initializes ACLGlobal->pool */ + ACL_ListHashInit(); + ACLGlobal->evalhash = oldACLGlobal->evalhash; + ACLGlobal->flushhash = oldACLGlobal->flushhash; + ACLGlobal->methodhash = oldACLGlobal->methodhash; + ACLGlobal->dbtypehash = oldACLGlobal->dbtypehash; + ACLGlobal->dbnamehash = oldACLGlobal->dbnamehash; + ACLGlobal->attrgetterhash = oldACLGlobal->attrgetterhash; + ACLGlobal->databasepool = oldACLGlobal->databasepool; + ACLGlobal->methodpool = oldACLGlobal->methodpool; + + // Mark all existing ACL Lists as stale. Delete any unreferenced ones. + PR_HashTableEnumerateEntries(oldACLGlobal->listhash, deletelists, NULL); + + // Delete the old master list. + ACL_ListDestroy(errp, oldACLGlobal->masterlist); + oldACLGlobal->masterlist = NULL; + PR_HashTableDestroy(oldACLGlobal->listhash); + oldACLGlobal->listhash = NULL; + PR_HashTableDestroy(oldACLGlobal->urihash); + oldACLGlobal->urihash = NULL; + PR_HashTableDestroy(oldACLGlobal->urigethash); + oldACLGlobal->urigethash = NULL; + pool_destroy(oldACLGlobal->pool); + oldACLGlobal->pool = NULL; + memset(oldACLGlobal, 0, sizeof(ACLGlobal_s)); + + + // Read in the ACLs again in lib/frame + if (AclCacheFlushRoutine) { + (*AclCacheFlushRoutine)(); + } + + ACL_CritExit(); + + return 0; +} + + +NSAPI_PUBLIC void +ACL_Restart(void *clntData) +{ + NSErr_t *errp = 0; + + NS_ASSERT(ACLGlobal); + NS_ASSERT(ACLGlobal->masterlist); + NS_ASSERT(ACLGlobal->listhash); + NS_ASSERT(ACLGlobal->urihash); + NS_ASSERT(ACLGlobal->urigethash); + NS_ASSERT(ACLGlobal->pool); + + // Unlike ACL_CacheFlush, this routine can be much more cavalier about + // freeing up memory, since there's guaranteed to be no users about at + // this time. + + ACL_DatabaseDestroy(); + ACL_MethodSetDefault(errp, ACL_METHOD_INVALID); + + // Mark all existing ACL Lists as stale. Delete any unreferenced ones + // (i.e. all of them) + PR_HashTableEnumerateEntries(ACLGlobal->listhash, restartdeletelists, NULL); + + // Delete the master list. + ACL_ListDestroy(errp, ACLGlobal->masterlist); + + ACL_LasHashDestroy(); + PR_HashTableDestroy(ACLGlobal->listhash); + PR_HashTableDestroy(ACLGlobal->urihash); + PR_HashTableDestroy(ACLGlobal->urigethash); + pool_destroy(ACLGlobal->pool); + + PERM_FREE(ACLGlobal); + ACLGlobal = NULL; + PERM_FREE(oldACLGlobal); + oldACLGlobal = NULL; + + return; +} |