Attempt fixing cache cleanup and strange iterator behaviors.
May crash on shutdown if there are entries in cache.
void
authenticateInit(Auth::ConfigVector * config)
{
- /* Do this first to clear memory and remove dead state on a reconfigure */
- if (proxy_auth_username_cache)
- Auth::User::CachedACLsReset();
-
/* If we do not have any auth config state to create stop now. */
if (!config)
return;
schemeCfg->init(schemeCfg);
}
- if (!proxy_auth_username_cache)
- Auth::User::cacheInit();
-
authenticateRegisterWithCacheManager(config);
}
void
authenticateReset(void)
{
- debugs(29, 2, HERE << "Reset authentication State.");
-
- /* free all username cache entries */
- hash_first(proxy_auth_username_cache);
- AuthUserHashPointer *usernamehash;
- while ((usernamehash = ((AuthUserHashPointer *) hash_next(proxy_auth_username_cache)))) {
- debugs(29, 5, HERE << "Clearing entry for user: " << usernamehash->user()->username());
- hash_remove_link(proxy_auth_username_cache, (hash_link *)usernamehash);
- delete usernamehash;
- }
+ debugs(29, 2, "Reset authentication State.");
+
+ // username cache is cleared via Runner registry
/* schedule shutdown of the helpers */
authenticateRotate();
Auth::TheConfig.clear();
}
-AuthUserHashPointer::AuthUserHashPointer(Auth::User::Pointer anAuth_user):
- auth_user(anAuth_user)
-{
- key = (void *)anAuth_user->userKey();
- next = NULL;
- hash_join(proxy_auth_username_cache, (hash_link *) this);
-}
-
-Auth::User::Pointer
-AuthUserHashPointer::user() const
-{
- return auth_user;
-}
-
std::vector<Auth::User::Pointer>
authenticateCachedUsersList()
{
#include "auth/User.h"
#include "hash.h"
-/**
- \ingroup AuthAPI
- *
- * This is used to link AuthUsers objects into the username cache.
- * Because some schemes may link in aliases to a user,
- * the link is not part of the AuthUser structure itself.
- *
- * Code must not hold onto copies of these objects.
- * They may exist only so long as the AuthUser being referenced
- * is recorded in the cache. Any caller using hash_remove_link
- * must then delete the AuthUserHashPointer.
- */
-class AuthUserHashPointer : public hash_link
-{
- MEMPROXY_CLASS(AuthUserHashPointer);
-
-public:
- AuthUserHashPointer(Auth::User::Pointer);
- ~AuthUserHashPointer() { auth_user = NULL; };
-
- Auth::User::Pointer user() const;
-
-private:
- Auth::User::Pointer auth_user;
-};
-
namespace Auth
{
class Scheme;
#include "SquidTime.h"
#include "Store.h"
-time_t Auth::User::last_discard = 0;
-
Auth::User::User(Auth::Config *aConfig, const char *aRequestRealm) :
auth_type(Auth::AUTH_UNKNOWN),
config(aConfig),
auth_type = Auth::AUTH_UNKNOWN;
}
-void
-Auth::User::cacheInit(void)
-{
- if (!proxy_auth_username_cache) {
- /* First time around, 7921 should be big enough */
- proxy_auth_username_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
- assert(proxy_auth_username_cache);
- eventAdd("User Cache Maintenance", cacheCleanup, NULL, ::Config.authenticateGCInterval, 1);
- last_discard = squid_curtime;
- }
-}
-
-void
-Auth::User::CachedACLsReset()
-{
- /*
- * This must complete all at once, because we are ensuring correctness.
- */
- AuthUserHashPointer *usernamehash;
- Auth::User::Pointer auth_user;
- debugs(29, 3, HERE << "Flushing the ACL caches for all users.");
- hash_first(proxy_auth_username_cache);
-
- while ((usernamehash = ((AuthUserHashPointer *) hash_next(proxy_auth_username_cache)))) {
- auth_user = usernamehash->user();
- /* free cached acl results */
- aclCacheMatchFlush(&auth_user->proxy_match_cache);
- }
-
- //new-style moved to UserNameCache::syncConfig()
-
- debugs(29, 3, HERE << "Finished.");
-}
-
-void
-Auth::User::cacheCleanup(void *)
-{
- /*
- * We walk the hash by username as that is the unique key we use.
- * For big hashs we could consider stepping through the cache, 100/200
- * entries at a time. Lets see how it flys first.
- */
- AuthUserHashPointer *usernamehash;
- Auth::User::Pointer auth_user;
- char const *username = NULL;
- debugs(29, 3, HERE << "Cleaning the user cache now");
- debugs(29, 3, HERE << "Current time: " << current_time.tv_sec);
- hash_first(proxy_auth_username_cache);
-
- while ((usernamehash = ((AuthUserHashPointer *) hash_next(proxy_auth_username_cache)))) {
- auth_user = usernamehash->user();
- username = auth_user->username();
-
- /* if we need to have indedendent expiry clauses, insert a module call
- * here */
- debugs(29, 4, HERE << "Cache entry:\n\tType: " <<
- auth_user->auth_type << "\n\tUsername: " << username <<
- "\n\texpires: " <<
- (long int) (auth_user->expiretime + ::Config.authenticateTTL) <<
- "\n\treferences: " << auth_user->LockCount());
-
- if (auth_user->expiretime + ::Config.authenticateTTL <= current_time.tv_sec) {
- debugs(29, 5, HERE << "Removing user " << username << " from cache due to timeout.");
-
- /* Old credentials are always removed. Existing users must hold their own
- * Auth::User::Pointer to the credentials. Cache exists only for finding
- * and re-using current valid credentials.
- */
- hash_remove_link(proxy_auth_username_cache, usernamehash);
- delete usernamehash;
- }
- }
-
- debugs(29, 3, HERE << "Finished cleaning the user cache.");
- eventAdd("User Cache Maintenance", cacheCleanup, NULL, ::Config.authenticateGCInterval, 1);
- last_discard = squid_curtime;
-}
-
void
Auth::User::clearIp()
{
#include "Notes.h"
#include "SBuf.h"
-class AuthUserHashPointer;
class StoreEntry;
namespace Auth
NotePairs notes;
public:
- static void cacheInit();
- static void CachedACLsReset();
static SBuf BuildUserKey(const char *username, const char *realm);
void absorb(Auth::User::Pointer from);
User(Auth::Config *, const char *requestRealm);
private:
- /**
- * Garbage Collection for the username cache.
- */
- static void cacheCleanup(void *unused);
- static time_t last_discard; /// Time of last username cache garbage collection.
-
/**
* DPW 2007-05-08
* The username_ memory will be allocated via
UserNameCache *self = static_cast<UserNameCache *>(data);
// cache entries with expiretime <= expirationTime are to be evicted
const time_t expirationTime = current_time.tv_sec - ::Config.authenticateTTL;
+
+ //XXX for some reason if evicting directly iterators are invalidated
+ // trying to defer deletion by using a queue
+ std::list<StoreType::iterator> toDelete;
const auto end = self->store_.end();
for (auto i = self->store_.begin(); i != end; ++i) {
+ debugs(29, 2, "considering " << i->first << "(expires in " <<
+ (expirationTime - i->second->expiretime) << " sec)");
if (i->second->expiretime <= expirationTime) {
- debugs(29, 2, "evicting " << i->first);
- self->store_.erase(i);
+ debugs(29, 2, "queueing for eviction " << i->first);
+ toDelete.push_back(i);
}
}
+ for (auto i : toDelete) {
+ debugs(29, 2, "evicting " << i->first);
+ self->store_.erase(i); //less efficient but safer than iter
+ }
eventAdd(self->cacheCleanupEventName.c_str(), &UserNameCache::Cleanup,
self, ::Config.authenticateGCInterval, 1);
}
#include "squid.h"
#include "auth/basic/Config.h"
#include "auth/basic/User.h"
-#include "auth/Gadgets.h" // for AuthUserHashPointer
#include "auth/UserNameCache.h"
#include "Debug.h"
#include "SquidConfig.h"
void
Auth::Basic::User::addToNameCache()
{
- /* AuthUserHashPointer will self-register with the username cache */
- new AuthUserHashPointer(this); //legacy
Cache()->insert(this);
}
#include "squid.h"
#include "auth/digest/Config.h"
#include "auth/digest/User.h"
-#include "auth/Gadgets.h" // for AuthUserHashPointer
#include "auth/UserNameCache.h"
#include "Debug.h"
#include "dlink.h"
void
Auth::Digest::User::addToNameCache()
{
- /* AuthUserHashPointer will self-register with the username cache */
- new AuthUserHashPointer(this); //legacy
Cache()->insert(this);
}
#include "squid.h"
#include "auth/Config.h"
-#include "auth/Gadgets.h" // for AuthUserHashPointer
#include "auth/negotiate/User.h"
#include "auth/UserNameCache.h"
#include "Debug.h"
void
Auth::Negotiate::User::addToNameCache()
{
- /* AuthUserHashPointer will self-register with the username cache */
- new AuthUserHashPointer(this); //legacy
Cache()->insert(this);
}
#include "squid.h"
#include "auth/Config.h"
-#include "auth/Gadgets.h" // for AuthUserHashPointer
#include "auth/ntlm/User.h"
#include "auth/UserNameCache.h"
#include "Debug.h"
void
Auth::Ntlm::User::addToNameCache()
{
- /* AuthUserHashPointer will self-register with the username cache */
- new AuthUserHashPointer(this); //legacy
Cache()->insert(this);
}
extern int store_swap_high; /* 0 */
extern size_t store_pages_max; /* 0 */
extern int64_t store_maxobjsize; /* 0 */
-extern hash_table *proxy_auth_username_cache; /* NULL */
extern int incoming_sockets_accepted;
#if _SQUID_WINDOWS_
extern unsigned int WIN32_Socks_initialized; /* 0 */
void authenticateRotate(void) STUB
void authenticateReset(void) STUB
-AuthUserHashPointer::AuthUserHashPointer(Auth::User::Pointer anAuth_user) STUB
-Auth::User::Pointer AuthUserHashPointer::user() const STUB_RETVAL(NULL)
-
#include "auth/Scheme.h"
#include <vector>
std::vector<Auth::Scheme::Pointer> *Auth::Scheme::_Schemes = NULL;