704 lines
21 KiB
C++
704 lines
21 KiB
C++
|
|
||
|
// Copyright (c) 1996-1999 Microsoft Corporation
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
//
|
||
|
// File: idt_ldap.cxx
|
||
|
//
|
||
|
// Contents: Intra-domain table based on LDAP.
|
||
|
//
|
||
|
// Classes:
|
||
|
//
|
||
|
// Functions:
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
// History: 18-Nov-96 BillMo Created.
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
// Codework:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
|
||
|
#include "pch.cxx"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include "trksvr.hxx"
|
||
|
|
||
|
|
||
|
CLdapOMTAddModify::CLdapOMTAddModify(
|
||
|
const CDomainRelativeObjId & ldKey,
|
||
|
const CDomainRelativeObjId & ldNew,
|
||
|
const CDomainRelativeObjId & ldBirth,
|
||
|
const ULONG & seqRefresh,
|
||
|
BYTE bFlags,
|
||
|
int mod_op )
|
||
|
:
|
||
|
|
||
|
_lsmClass(s_objectClass, s_linkTrackOMTEntry, 0),
|
||
|
|
||
|
_lbmCurrentLocation( s_currentLocation, reinterpret_cast<PCCH>(&ldNew), sizeof(ldNew), mod_op ),
|
||
|
_lbmBirthLocation( s_birthLocation, reinterpret_cast<PCCH>(&ldBirth), sizeof(ldBirth), mod_op ),
|
||
|
_ltvRefresh( seqRefresh ),
|
||
|
_lsmRefresh( s_timeRefresh, _ltvRefresh, mod_op ),
|
||
|
_lbmFlags( s_oMTIndxGuid, reinterpret_cast<PCCH>(&bFlags), sizeof(BYTE), mod_op )
|
||
|
|
||
|
{
|
||
|
int i = 0;
|
||
|
if (mod_op == LDAP_MOD_ADD)
|
||
|
{
|
||
|
_mods[i++] = &_lsmClass._mod;
|
||
|
_mods[i++] = &_lbmFlags._mod;
|
||
|
}
|
||
|
_mods[i++] = &_lbmCurrentLocation._mod;
|
||
|
|
||
|
if (ldKey != ldBirth)
|
||
|
_mods[i++] = &_lbmBirthLocation._mod;
|
||
|
|
||
|
_mods[i++] = &_lsmRefresh._mod;
|
||
|
_mods[i++] = NULL;
|
||
|
|
||
|
TrkAssert(i <= sizeof(_mods)/sizeof(_mods[0]));
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CIntraDomainTable::Initialize( CTrkSvrConfiguration *pTrkSvrConfiguration, CQuotaTable* pqtable )
|
||
|
{
|
||
|
_fInitializeCalled = TRUE;
|
||
|
_pqtable = pqtable;
|
||
|
_pTrkSvrConfiguration = pTrkSvrConfiguration;
|
||
|
_QuotaReported.Initialize();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CIntraDomainTable::UnInitialize()
|
||
|
{
|
||
|
if (_fInitializeCalled)
|
||
|
{
|
||
|
}
|
||
|
_fInitializeCalled = FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// CIntraDomainTable::Add
|
||
|
//
|
||
|
// Add an entry to the move table. Return TRUE if the entry was added, but
|
||
|
// didn't already exist. Return FALSE if the entry already exists. If
|
||
|
// there's an error, raise an exception.
|
||
|
//
|
||
|
//+----------------------------------------------------------------------------
|
||
|
|
||
|
BOOL
|
||
|
CIntraDomainTable::Add(const CDomainRelativeObjId &ldKey,
|
||
|
const CDomainRelativeObjId &ldNew,
|
||
|
const CDomainRelativeObjId &ldBirth,
|
||
|
BOOL *pfQuotaExceeded OPTIONAL )
|
||
|
{
|
||
|
int err;
|
||
|
BYTE bFlags = QFLAG_UNCOUNTED;
|
||
|
|
||
|
CLdapIdtKeyDn dnKey(GetBaseDn(), ldKey);
|
||
|
|
||
|
// The following constructor sets up the mods array for
|
||
|
// the ldap_add_s call that we're about to do.
|
||
|
|
||
|
CLdapOMTAddModify lam( ldKey, // Key
|
||
|
ldNew, // New droid
|
||
|
ldBirth, // Birth droid
|
||
|
// Current sequence number
|
||
|
_pRefreshSequenceStorage->GetSequenceNumber(),
|
||
|
bFlags, // Flags, will be pointed to
|
||
|
// (so can't e.g. use a #define value)
|
||
|
LDAP_MOD_ADD); // Add this element
|
||
|
|
||
|
// Return FALSE here means that we pretend to the caller that the entry
|
||
|
// already exists. We don't want to raise an exception here. Our caller
|
||
|
// always tries to add the entry, if the add fails because the entry
|
||
|
// already exists, the caller will then try to modify the entry. If the
|
||
|
// quota has been exceeded, we don't want to add more entries, but we
|
||
|
// still want entries already in the table to be modifiable. So instead of
|
||
|
// raising an exception, we really want the caller to try to modify the
|
||
|
// entry instead.
|
||
|
|
||
|
if(_pqtable->IsMoveQuotaExceeded())
|
||
|
{
|
||
|
if( NULL != pfQuotaExceeded )
|
||
|
*pfQuotaExceeded = TRUE;
|
||
|
|
||
|
if( !_QuotaReported.IsSet() )
|
||
|
{
|
||
|
_QuotaReported.Set();
|
||
|
TrkReportEvent( EVENT_TRK_SERVICE_MOVE_QUOTA_EXCEEDED, EVENTLOG_WARNING_TYPE,
|
||
|
TRKREPORT_LAST_PARAM );
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_QuotaReported.Clear();
|
||
|
}
|
||
|
|
||
|
err = ldap_add_s(Ldap(), dnKey, lam._mods);
|
||
|
if (err == LDAP_SUCCESS)
|
||
|
{
|
||
|
{
|
||
|
LDAPMod* mods[2];
|
||
|
BYTE bFlags = QFLAG_UNCOUNTED;
|
||
|
CLdapBinaryMod lbm(s_oMTIndxGuid, reinterpret_cast<PCCH>(&bFlags), sizeof(BYTE), LDAP_MOD_REPLACE);
|
||
|
|
||
|
mods[0] = &lbm._mod;
|
||
|
mods[1] = NULL;
|
||
|
|
||
|
err = ldap_modify_s(Ldap(), dnKey, mods);
|
||
|
}
|
||
|
|
||
|
_pqtable->IncrementMoveCountCache();
|
||
|
return(TRUE);
|
||
|
}
|
||
|
else
|
||
|
if (err == LDAP_ALREADY_EXISTS)
|
||
|
{
|
||
|
return(FALSE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TrkRaiseWin32Error(LdapMapErrorToWin32(err));
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// TRUE if found and deleted, FALSE if not found, exception on other errors
|
||
|
|
||
|
BOOL
|
||
|
CIntraDomainTable::Delete(const CDomainRelativeObjId &ldKey)
|
||
|
{
|
||
|
int err;
|
||
|
CLdapIdtKeyDn dnKey(GetBaseDn(), ldKey);
|
||
|
BOOL fFound;
|
||
|
|
||
|
fFound = _pqtable->UpdateFlags(Ldap(), dnKey, QFLAG_DELETED);
|
||
|
if( fFound )
|
||
|
_pqtable->DecrementMoveCountCache();
|
||
|
return fFound;
|
||
|
}
|
||
|
|
||
|
// TRUE if entry exists and modified, FALSE if not existent, exception otherwise
|
||
|
BOOL
|
||
|
CIntraDomainTable::Modify(const CDomainRelativeObjId &ldKey,
|
||
|
const CDomainRelativeObjId &ldNew,
|
||
|
const CDomainRelativeObjId &ldBirth )
|
||
|
{
|
||
|
int err;
|
||
|
CLdapIdtKeyDn dnKey(GetBaseDn(), ldKey);
|
||
|
CLdapOMTAddModify lam( ldKey,
|
||
|
ldNew,
|
||
|
ldBirth,
|
||
|
_pRefreshSequenceStorage->GetSequenceNumber(),
|
||
|
0, // Only used with LDAP_MOD_ADD
|
||
|
LDAP_MOD_REPLACE);
|
||
|
|
||
|
err = ldap_modify_s(Ldap(), dnKey, lam._mods);
|
||
|
|
||
|
if (err == LDAP_SUCCESS)
|
||
|
{
|
||
|
return(TRUE);
|
||
|
}
|
||
|
else
|
||
|
if (err == LDAP_NO_SUCH_OBJECT)
|
||
|
{
|
||
|
return(FALSE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TrkRaiseWin32Error(LdapMapErrorToWin32(err));
|
||
|
return(FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// must leave outputs unchanged if returning FALSE
|
||
|
BOOL
|
||
|
CIntraDomainTable::Query(const CDomainRelativeObjId &ldKey,
|
||
|
CDomainRelativeObjId *pldNew,
|
||
|
CDomainRelativeObjId *pldBirth,
|
||
|
BOOL *pfDeleted OPTIONAL,
|
||
|
BOOL *pfCounted OPTIONAL )
|
||
|
{
|
||
|
int err;
|
||
|
TCHAR *aptszAttrs[] = { const_cast<TCHAR*>(s_currentLocation),
|
||
|
const_cast<TCHAR*>(s_birthLocation),
|
||
|
const_cast<TCHAR*>(s_oMTIndxGuid),
|
||
|
NULL };
|
||
|
LDAPMessage * pRes = NULL;
|
||
|
CLdapIdtKeyDn dnKey(GetBaseDn(), ldKey);
|
||
|
BOOL fFound = FALSE;
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
err = ldap_search_s( Ldap(),
|
||
|
dnKey,
|
||
|
LDAP_SCOPE_BASE,
|
||
|
TEXT("(objectclass=*)"),
|
||
|
aptszAttrs,
|
||
|
0, // attribute types and values are wanted
|
||
|
&pRes );
|
||
|
|
||
|
if (err == LDAP_SUCCESS)
|
||
|
{
|
||
|
// found it, lets get the attributes out
|
||
|
|
||
|
if (ldap_count_entries(Ldap(), pRes) == 1)
|
||
|
{
|
||
|
LDAPMessage * pEntry = ldap_first_entry(Ldap(), pRes);
|
||
|
if (pEntry == NULL)
|
||
|
{
|
||
|
TrkRaiseWin32Error(LdapMapErrorToWin32(Ldap()->ld_errno));
|
||
|
}
|
||
|
|
||
|
fFound = Query( Ldap(), pEntry, ldKey, pldNew, pldBirth, pfDeleted, pfCounted );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
if (err != LDAP_NO_SUCH_OBJECT)
|
||
|
{
|
||
|
TrkRaiseWin32Error(LdapMapErrorToWin32(err));
|
||
|
}
|
||
|
}
|
||
|
__finally
|
||
|
{
|
||
|
if (NULL != pRes)
|
||
|
ldap_msgfree(pRes);
|
||
|
}
|
||
|
|
||
|
return(fFound);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
CIntraDomainTable::Query( LDAP* pLdap,
|
||
|
LDAPMessage *pEntry,
|
||
|
const CDomainRelativeObjId ldKey,
|
||
|
CDomainRelativeObjId *pldNew,
|
||
|
CDomainRelativeObjId *pldBirth,
|
||
|
BOOL *pfDeleted OPTIONAL,
|
||
|
BOOL *pfCounted OPTIONAL )
|
||
|
{
|
||
|
BOOL fFound = FALSE;
|
||
|
struct berval **ppbvCurrentLocation = NULL;
|
||
|
struct berval **ppbvBirthLocation = NULL;
|
||
|
struct berval **ppbvQuotaFlags = NULL;
|
||
|
BYTE bQuotaFlags = 0;
|
||
|
|
||
|
if( NULL != pfDeleted )
|
||
|
*pfDeleted = FALSE;
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
ppbvBirthLocation = ldap_get_values_len(pLdap, pEntry,
|
||
|
const_cast<TCHAR*>(s_birthLocation) );
|
||
|
|
||
|
if (NULL != ppbvBirthLocation
|
||
|
&&
|
||
|
sizeof(*pldBirth) > (*ppbvBirthLocation)->bv_len)
|
||
|
{
|
||
|
TrkLog((TRKDBG_ERROR, TEXT("Couldn't get current location for %s"),
|
||
|
(const TCHAR*)CDebugString(ldKey) ));
|
||
|
TrkRaiseWin32Error( LdapMapErrorToWin32(pLdap->ld_errno) );
|
||
|
}
|
||
|
|
||
|
ppbvCurrentLocation = ldap_get_values_len(pLdap, pEntry,
|
||
|
const_cast<TCHAR*>(s_currentLocation) );
|
||
|
if (NULL == ppbvCurrentLocation
|
||
|
||
|
||
|
sizeof(*pldNew) > (*ppbvCurrentLocation)->bv_len)
|
||
|
{
|
||
|
TrkLog((TRKDBG_ERROR, TEXT("Couldn't get current location for %s"),
|
||
|
(const TCHAR*)CDebugString(ldKey) ));
|
||
|
TrkRaiseWin32Error( LdapMapErrorToWin32(pLdap->ld_errno) );
|
||
|
}
|
||
|
|
||
|
ppbvQuotaFlags = ldap_get_values_len(pLdap, pEntry,
|
||
|
const_cast<TCHAR*>(s_oMTIndxGuid) );
|
||
|
|
||
|
if (NULL != ppbvQuotaFlags
|
||
|
&&
|
||
|
sizeof(BYTE) <= (*ppbvQuotaFlags)->bv_len)
|
||
|
{
|
||
|
bQuotaFlags = *(BYTE*)(*ppbvQuotaFlags)->bv_val;
|
||
|
}
|
||
|
|
||
|
if( NULL != pfCounted )
|
||
|
{
|
||
|
if( bQuotaFlags & QFLAG_UNCOUNTED )
|
||
|
*pfCounted = FALSE;
|
||
|
else
|
||
|
*pfCounted = TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
if( bQuotaFlags & QFLAG_DELETED )
|
||
|
{
|
||
|
if( NULL != pfDeleted )
|
||
|
*pfDeleted = TRUE;
|
||
|
|
||
|
TrkLog(( TRKDBG_IDT, TEXT("IdtQuery: Entry marked deleted will be ignored (0x%x): %s"),
|
||
|
bQuotaFlags,
|
||
|
(const TCHAR*)CDebugString(ldKey) ));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*pldNew = *reinterpret_cast<CDomainRelativeObjId*>( (*ppbvCurrentLocation)->bv_val );
|
||
|
|
||
|
if (NULL != ppbvBirthLocation)
|
||
|
*pldBirth = *reinterpret_cast<CDomainRelativeObjId*>( (*ppbvBirthLocation)->bv_val );
|
||
|
else
|
||
|
*pldBirth = ldKey;
|
||
|
|
||
|
fFound = TRUE;
|
||
|
}
|
||
|
}
|
||
|
__finally
|
||
|
{
|
||
|
if (NULL != ppbvCurrentLocation)
|
||
|
ldap_value_free_len(ppbvCurrentLocation);
|
||
|
|
||
|
if (NULL != ppbvBirthLocation)
|
||
|
ldap_value_free_len(ppbvBirthLocation);
|
||
|
|
||
|
if (NULL != ppbvQuotaFlags)
|
||
|
ldap_value_free_len(ppbvQuotaFlags);
|
||
|
}
|
||
|
|
||
|
return( fFound );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// CIntraDomainTable::Touch
|
||
|
//
|
||
|
// Update the refresh attribute for an entry in the move table.
|
||
|
// Return TRUE if the entry exists and was touched, FALSE if it
|
||
|
// doesn't exist, and raise an exception if there's an error.
|
||
|
//
|
||
|
//+----------------------------------------------------------------------------
|
||
|
|
||
|
// BUGBUG: if we ever move to per-user quotas,
|
||
|
// check ownership of entry being touched.
|
||
|
|
||
|
BOOL
|
||
|
CIntraDomainTable::Touch(
|
||
|
const CDomainRelativeObjId &ldKey
|
||
|
)
|
||
|
{
|
||
|
BOOL fReturn = FALSE;
|
||
|
int err;
|
||
|
CLdapTimeValue ltvRefresh( _pRefreshSequenceStorage->GetSequenceNumber());
|
||
|
CLdapStringMod lsmRefresh( s_timeRefresh, ltvRefresh, LDAP_MOD_REPLACE );
|
||
|
CLdapIdtKeyDn dnKey(GetBaseDn(), ldKey);
|
||
|
TCHAR ** pptszRefresh = NULL;
|
||
|
LDAPMessage * pEntry = NULL;
|
||
|
LDAPMessage* pRes = NULL;
|
||
|
|
||
|
LDAPMod * mods[2];
|
||
|
CObjId objZero;
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
//
|
||
|
// if the birth id is zero, then it is invalid and not worth doing a refresh
|
||
|
//
|
||
|
|
||
|
if (ldKey.GetObjId() == objZero)
|
||
|
{
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check to see if the object already has a recent sequence number.
|
||
|
//
|
||
|
|
||
|
TCHAR* rgptszAttrs[2];
|
||
|
rgptszAttrs[0] = const_cast<TCHAR*>(s_timeRefresh);
|
||
|
rgptszAttrs[1] = NULL;
|
||
|
|
||
|
err = ldap_search_s(Ldap(),
|
||
|
dnKey,
|
||
|
LDAP_SCOPE_BASE,
|
||
|
TEXT("(ObjectClass=*)"),
|
||
|
rgptszAttrs,
|
||
|
0,
|
||
|
&pRes);
|
||
|
|
||
|
if (err == LDAP_SUCCESS)
|
||
|
{
|
||
|
// The search call worked, but did we find an object?
|
||
|
if( 1 == ldap_count_entries(Ldap(), pRes) )
|
||
|
{
|
||
|
// The object already exists
|
||
|
pEntry = ldap_first_entry(Ldap(), pRes);
|
||
|
if( NULL != pEntry )
|
||
|
{
|
||
|
// Get the refresh counter
|
||
|
pptszRefresh = ldap_get_values( Ldap(), pEntry, const_cast<TCHAR*>(s_timeRefresh) );
|
||
|
if( NULL != pptszRefresh )
|
||
|
{
|
||
|
SequenceNumber seqRefresh = 0;
|
||
|
if( 1 == _stscanf( *pptszRefresh, TEXT("%d"), &seqRefresh ))
|
||
|
{
|
||
|
// Is the refresh counter already set to a recent value?
|
||
|
// We'll consider it recent enough if it's within half of the
|
||
|
// refresh cycle (15 days)
|
||
|
|
||
|
// First, how long is the GC timer in seconds?
|
||
|
LONG lGCTimerInSeconds = _pTrkSvrConfiguration->GetGCPeriod() // 30 days in seconds
|
||
|
/ _pTrkSvrConfiguration->GetGCDivisor(); // => 1 day in seconds
|
||
|
|
||
|
// Next, how many ticks is half the period?
|
||
|
LONG lWindow = _pTrkSvrConfiguration->GetGCPeriod() // 30 days (in seconds)
|
||
|
/ 2 // => 15 days (in seconds)
|
||
|
/ lGCTimerInSeconds; // => 15
|
||
|
|
||
|
TrkLog(( TRKDBG_WARNING, TEXT("Window = %d"), lWindow ));
|
||
|
|
||
|
if( seqRefresh + lWindow
|
||
|
>= _pRefreshSequenceStorage->GetSequenceNumber()
|
||
|
)
|
||
|
{
|
||
|
TrkLog(( TRKDBG_GARBAGE_COLLECT | TRKDBG_IDT,
|
||
|
TEXT("Not touching %s with %d, seq %d already set"),
|
||
|
(const TCHAR*)CDebugString(ldKey),
|
||
|
_pRefreshSequenceStorage->GetSequenceNumber(),
|
||
|
seqRefresh ));
|
||
|
__leave;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (err == LDAP_NO_SUCH_OBJECT)
|
||
|
{
|
||
|
TrkLog((TRKDBG_GARBAGE_COLLECT | TRKDBG_IDT,
|
||
|
TEXT("Touch: object %s not found"),
|
||
|
(const TCHAR*) CDebugString(ldKey) ));
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Set the correct sequence number
|
||
|
//
|
||
|
|
||
|
mods[0] = &lsmRefresh._mod;
|
||
|
mods[1] = NULL;
|
||
|
|
||
|
err = ldap_modify_s(Ldap(), dnKey, mods);
|
||
|
|
||
|
if (err == LDAP_SUCCESS)
|
||
|
{
|
||
|
TrkLog((TRKDBG_GARBAGE_COLLECT | TRKDBG_IDT,
|
||
|
TEXT("Touch: object %s touched"),
|
||
|
(const TCHAR*) CDebugString(ldKey) ));
|
||
|
fReturn = TRUE;
|
||
|
__leave;
|
||
|
}
|
||
|
else
|
||
|
if (err == LDAP_NO_SUCH_OBJECT)
|
||
|
{
|
||
|
TrkLog((TRKDBG_GARBAGE_COLLECT | TRKDBG_IDT,
|
||
|
TEXT("Touch: object %s not found"),
|
||
|
(const TCHAR*) CDebugString(ldKey) ));
|
||
|
__leave;
|
||
|
}
|
||
|
else
|
||
|
if (err == LDAP_NO_SUCH_ATTRIBUTE)
|
||
|
{
|
||
|
TrkLog((TRKDBG_GARBAGE_COLLECT | TRKDBG_SVR,
|
||
|
TEXT("Touch: object %s attribute not found"),
|
||
|
(const TCHAR*) CDebugString(ldKey) ));
|
||
|
|
||
|
// deal with old server data
|
||
|
CLdapStringMod lsmRefresh( s_timeRefresh, ltvRefresh, LDAP_MOD_ADD );
|
||
|
mods[0] = &lsmRefresh._mod;
|
||
|
|
||
|
err = ldap_modify_s(Ldap(), dnKey, mods);
|
||
|
}
|
||
|
|
||
|
if (err != LDAP_SUCCESS)
|
||
|
{
|
||
|
TrkLog((TRKDBG_GARBAGE_COLLECT | TRKDBG_IDT,
|
||
|
TEXT("Touch: object %s --> exceptional error"),
|
||
|
(const TCHAR*) CDebugString(ldKey) ));
|
||
|
__leave;
|
||
|
}
|
||
|
}
|
||
|
__except( BreakOnDebuggableException() )
|
||
|
{
|
||
|
TrkLog(( TRKDBG_ERROR, TEXT("Ignoring exception during IDT::Touch (%08x)"), GetExceptionCode() ));
|
||
|
}
|
||
|
|
||
|
if (pptszRefresh != NULL)
|
||
|
ldap_value_free(pptszRefresh);
|
||
|
if(pRes != NULL)
|
||
|
ldap_msgfree(pRes);
|
||
|
|
||
|
return( fReturn );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
ULONG
|
||
|
CIntraDomainTable::GarbageCollect( SequenceNumber seqCurrent, SequenceNumber seqOldestToKeep, const BOOL * pfAbort )
|
||
|
{
|
||
|
CLdapIdtKeyDn dn(GetBaseDn());
|
||
|
TCHAR * apszAttrs[3];
|
||
|
GC_ENUM_CONTEXT EnumContext;
|
||
|
|
||
|
apszAttrs[0] = const_cast<TCHAR*>(s_Cn);
|
||
|
apszAttrs[1] = const_cast<TCHAR*>(s_timeRefresh);
|
||
|
apszAttrs[2] = 0;
|
||
|
|
||
|
TrkLog(( TRKDBG_GARBAGE_COLLECT | TRKDBG_IDT, TEXT("GC-ing move table (%d/%d)"),
|
||
|
seqCurrent, seqOldestToKeep ));
|
||
|
|
||
|
memset( &EnumContext, 0, sizeof(EnumContext) );
|
||
|
EnumContext.seqOldestToKeep = seqOldestToKeep;
|
||
|
EnumContext.seqCurrent = seqCurrent;
|
||
|
EnumContext.pfAbort = pfAbort;
|
||
|
EnumContext.dwRepetitiveTaskDelay = _pTrkSvrConfiguration->GetRepetitiveTaskDelay();
|
||
|
EnumContext.pqtable = _pqtable;
|
||
|
|
||
|
if (!LdapEnumerate(
|
||
|
Ldap(),
|
||
|
dn,
|
||
|
LDAP_SCOPE_ONELEVEL,
|
||
|
TEXT("(objectClass=*)"),
|
||
|
apszAttrs,
|
||
|
GcEnumerateCallback,
|
||
|
&EnumContext ))
|
||
|
{
|
||
|
TrkRaiseException(TRK_E_SERVICE_STOPPING);
|
||
|
}
|
||
|
|
||
|
TrkLog(( TRKDBG_GARBAGE_COLLECT | TRKDBG_IDT,
|
||
|
TEXT("GC-ed %d entries from the move table"),
|
||
|
EnumContext.cEntries ));
|
||
|
|
||
|
_pqtable->OnMoveTableGcComplete( EnumContext.cEntries );
|
||
|
|
||
|
|
||
|
return EnumContext.cEntries;
|
||
|
}
|
||
|
|
||
|
#if DBG
|
||
|
void
|
||
|
CIntraDomainTable::PurgeAll()
|
||
|
{
|
||
|
int err;
|
||
|
TCHAR *apszAttrs[2] = { TEXT("cn"), NULL };
|
||
|
LDAPMessage * pRes;
|
||
|
TCHAR tszObjectMoveTable[MAX_PATH+1];
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
_tcscpy(tszObjectMoveTable, s_ObjectMoveTableRDN);
|
||
|
_tcscat(tszObjectMoveTable, GetBaseDn());
|
||
|
|
||
|
err = ldap_search_s( Ldap(),
|
||
|
tszObjectMoveTable,
|
||
|
LDAP_SCOPE_ONELEVEL,
|
||
|
TEXT("(objectclass=*)"),
|
||
|
apszAttrs,
|
||
|
0, // attribute types and values are wanted
|
||
|
&pRes );
|
||
|
|
||
|
if (err == LDAP_SUCCESS)
|
||
|
{
|
||
|
// found it, lets get the attributes out
|
||
|
|
||
|
int cEntries = ldap_count_entries(Ldap(), pRes);
|
||
|
LDAPMessage * pEntry = ldap_first_entry(Ldap(), pRes);
|
||
|
if (pEntry != NULL)
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
TCHAR * ptszDn = ldap_get_dn(Ldap(), pEntry);
|
||
|
|
||
|
int errd = ldap_delete_s(Ldap(),ptszDn);
|
||
|
|
||
|
TrkLog((TRKDBG_ERROR, TEXT("Purged %s status=%d"), ptszDn, errd));
|
||
|
ldap_memfree(ptszDn);
|
||
|
|
||
|
} while ( pEntry = ldap_next_entry(Ldap(), pEntry));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
__finally
|
||
|
{
|
||
|
if (err == LDAP_SUCCESS)
|
||
|
{
|
||
|
ldap_msgfree(pRes);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void
|
||
|
CDomainRelativeObjId::FillLdapIdtKeyBuffer(TCHAR * const pchCN,
|
||
|
DWORD cch) const
|
||
|
{
|
||
|
TCHAR *pchBuf = pchCN;
|
||
|
_tcscpy(pchBuf, TEXT("CN="));
|
||
|
pchBuf = pchBuf + 3;
|
||
|
_volume.Stringize(pchBuf);
|
||
|
_object.Stringize(pchBuf);
|
||
|
TrkAssert(pchBuf <= pchCN+cch);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CDomainRelativeObjId::ReadLdapIdtKeyBuffer(const TCHAR * pchCN )
|
||
|
{
|
||
|
const TCHAR *pchBuf;
|
||
|
Init();
|
||
|
if( 0 == _tcsncmp( pchCN, TEXT("CN="), 3 ))
|
||
|
{
|
||
|
pchBuf = &pchCN[3];
|
||
|
if( !_volume.Unstringize(pchBuf)
|
||
|
||
|
||
|
!_object.Unstringize(pchBuf) )
|
||
|
{
|
||
|
TrkLog(( TRKDBG_ERROR, TEXT("Couldn't unstringize droid from %s"), pchCN ));
|
||
|
Init();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CDomainRelativeObjId::InitFromLdapBuffer(char * pVolumeId, int cbVolumeId,
|
||
|
char * pObjId, int cbObjId)
|
||
|
{
|
||
|
DWORD iBuf = 0;
|
||
|
|
||
|
if (cbVolumeId != sizeof(_volume) ||
|
||
|
cbObjId != sizeof(_object))
|
||
|
{
|
||
|
TrkRaiseException(TRK_E_CORRUPT_IDT);
|
||
|
}
|
||
|
|
||
|
memcpy(&_volume, pVolumeId, sizeof(_volume));
|
||
|
memcpy(&_object, pObjId, sizeof(_object));
|
||
|
}
|
||
|
|
||
|
|