windows-nt/Source/XPSP1/NT/net/ias/providers/ntuser/ldap/ntcache.cpp
2020-09-26 16:20:57 +08:00

152 lines
2.7 KiB
C++

///////////////////////////////////////////////////////////////////////////////
//
// FILE
//
// ntcache.cpp
//
// SYNOPSIS
//
// Defines the class NTCache.
//
// MODIFICATION HISTORY
//
// 05/11/1998 Original version.
// 03/12/1999 Improve locking granularity.
//
///////////////////////////////////////////////////////////////////////////////
#include <ias.h>
#include <ntcache.h>
//////////
// Utility function for getting the current system time as a 64-bit integer.
//////////
inline DWORDLONG GetSystemTimeAsDWORDLONG() throw ()
{
ULARGE_INTEGER ft;
GetSystemTimeAsFileTime((LPFILETIME)&ft);
return ft.QuadPart;
}
NTCache::~NTCache()
{
clear();
}
void NTCache::clear() throw ()
{
Lock();
// Release all the domains.
for (DomainTable::iterator i = cache.begin(); i.more(); ++i)
{
(*i)->Release();
}
// Clear the hash table.
cache.clear();
Unlock();
}
DWORD NTCache::getConnection(PCWSTR domainName, LDAPConnection** cxn) throw ()
{
_ASSERT(cxn != NULL);
NTDomain* domain;
DWORD status = getDomain(domainName, &domain);
if (status == NO_ERROR)
{
status = domain->getConnection(cxn);
domain->Release();
}
else
{
*cxn = NULL;
}
return status;
}
DWORD NTCache::getDomain(PCWSTR domainName, NTDomain** domain) throw ()
{
_ASSERT(domain != NULL);
DWORD status = NO_ERROR;
Lock();
// Check if we already have an entry for this domainName.
NTDomain* const* existing = cache.find(domainName);
if (existing)
{
(*domain = *existing)->AddRef();
}
else
{
// We don't have this domain, so create a new one ...
*domain = NTDomain::createInstance(domainName);
// Evict expired entries.
evict();
try
{
// Try to insert the domain ...
cache.multi_insert(*domain);
// ... and AddRef if we succeeded.
(*domain)->AddRef();
}
catch (...)
{
// We don't care if the insert failed.
}
}
Unlock();
return *domain ? NO_ERROR : ERROR_NOT_ENOUGH_MEMORY;
}
NTDomain::Mode NTCache::getMode(PCWSTR domainName) throw ()
{
NTDomain::Mode mode = NTDomain::MODE_UNKNOWN;
NTDomain* domain;
if (getDomain(domainName, &domain) == NO_ERROR)
{
mode = domain->getMode();
domain->Release();
}
return mode;
}
void NTCache::evict() throw ()
{
//////////
// Note: This method is not serialized.
//////////
DWORDLONG now = GetSystemTimeAsDWORDLONG();
DomainTable::iterator i = cache.begin();
while (i.more())
{
if ((*i)->isObsolete(now))
{
// The entry has expired, so release and erase.
(*i)->Release();
cache.erase(i);
}
else
{
++i;
}
}
}