summaryrefslogtreecommitdiffstats
path: root/lib/libaccess/aclflush.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libaccess/aclflush.cpp')
-rw-r--r--lib/libaccess/aclflush.cpp178
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;
+}