#include "CRefTable.h"
#include "CLog.h"
#include "DSNetworkUtilities.h"
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/sysctl.h> // for struct kinfo_proc and sysctl()
#include <syslog.h> // for syslog()
using namespace std;
extern dsBool gLogAPICalls;
extern uInt32 gRefCountWarningLimit;
extern uInt32 gDaemonIPAddress;
CRefTable::CRefTable ( RefDeallocateProc *deallocProc )
{
fRefCleanUpEntriesHead = nil;
fRefCleanUpEntriesTail = nil;
fClientPIDListLock = new DSMutexSemaphore();
fTableCount = 0;
::memset( fRefTables, 0, sizeof( fRefTables ) );
fDeallocProc = deallocProc;
}
CRefTable::~CRefTable ( void )
{
uInt32 i = 1;
uInt32 j = 1;
for ( i = 1; i <= kMaxTables; i++ ) {
if ( fRefTables[ i ] != nil )
{
for (j=0; j< kMaxTableItems; j++)
{
if (fRefTables[ i ]->fTableData[j] != nil)
{
free(fRefTables[ i ]->fTableData[j]);
fRefTables[ i ]->fTableData[j] = nil;
}
}
free( fRefTables[ i ] ); fRefTables[ i ] = nil;
}
}
delete(fClientPIDListLock);
fClientPIDListLock = nil;
}
void CRefTable::Lock ( )
{
fTableMutex.Wait();
}
void CRefTable::Unlock ( )
{
fTableMutex.Signal();
}
tDirStatus CRefTable::VerifyReference ( tDirReference inDirRef,
uInt32 inType,
CServerPlugin **outPlugin,
sInt32 inPID,
uInt32 inIPAddress,
bool inDaemonPID_OK )
{
tDirStatus siResult = eDSNoErr;
sRefEntry *refData = nil;
sPIDInfo *pPIDInfo = nil;
siResult = GetReference( inDirRef, &refData );
if ( siResult == eDSNoErr )
{
if ( refData->fType != inType )
{
DBGLOG1( kLogHandler, "Given reference value of <%u> found but does not match reference type.", inDirRef);
siResult = eDSInvalidRefType;
}
else
{
siResult = eDSInvalidRefType;
if ( inDaemonPID_OK && inPID == 0 )
{
siResult = eDSNoErr;
}
else if ( (refData->fPID == inPID) && (refData->fIPAddress == inIPAddress) )
{
siResult = eDSNoErr;
}
else
{
pPIDInfo = refData->fChildPID;
while ( (pPIDInfo != nil) && (siResult != eDSNoErr) )
{
if ( (pPIDInfo->fPID == inPID) && (pPIDInfo->fIPAddress == inIPAddress) )
{
siResult = eDSNoErr;
}
pPIDInfo = pPIDInfo->fNext;
}
}
if (siResult == eDSNoErr)
{
if ( outPlugin != nil )
{
*outPlugin = refData->fPlugin;
}
}
}
}
return( siResult );
}
tDirStatus CRefTable::VerifyDirRef ( tDirReference inDirRef,
CServerPlugin **outPlugin,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->VerifyReference( inDirRef, eDirectoryRefType, outPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::VerifyNodeRef ( tDirNodeReference inDirNodeRef,
CServerPlugin **outPlugin,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->VerifyReference( inDirNodeRef, eNodeRefType, outPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::VerifyRecordRef ( tRecordReference inRecordRef,
CServerPlugin **outPlugin,
sInt32 inPID,
uInt32 inIPAddress,
bool inDaemonPID_OK )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->VerifyReference( inRecordRef, eRecordRefType, outPlugin, inPID, inIPAddress, inDaemonPID_OK );
}
return( siResult );
}
tDirStatus CRefTable::VerifyAttrListRef ( tAttributeListRef inAttributeListRef,
CServerPlugin **outPlugin,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->VerifyReference( inAttributeListRef, eAttrListRefType, outPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::VerifyAttrValueRef ( tAttributeValueListRef inAttributeValueListRef,
CServerPlugin **outPlugin,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->VerifyReference( inAttributeValueListRef, eAttrValueListRefType, outPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::NewDirRef ( uInt32 *outNewRef,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->GetNewRef( outNewRef, 0, eDirectoryRefType, nil, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::NewNodeRef ( uInt32 *outNewRef,
CServerPlugin *inPlugin,
uInt32 inParentID,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->GetNewRef( outNewRef, inParentID, eNodeRefType, inPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::NewRecordRef ( uInt32 *outNewRef,
CServerPlugin *inPlugin,
uInt32 inParentID,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->GetNewRef( outNewRef, inParentID, eRecordRefType, inPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::NewAttrListRef ( uInt32 *outNewRef,
CServerPlugin *inPlugin,
uInt32 inParentID,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->GetNewRef( outNewRef, inParentID, eAttrListRefType, inPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::NewAttrValueRef ( uInt32 *outNewRef,
CServerPlugin *inPlugin,
uInt32 inParentID,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->GetNewRef( outNewRef, inParentID, eAttrValueListRefType, inPlugin, inPID, inIPAddress );
}
return( siResult );
}
tDirStatus CRefTable::RemoveDirRef ( uInt32 inDirRef,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->RemoveRef( inDirRef, eDirectoryRefType, inPID, inIPAddress, true );
}
return( siResult );
}
tDirStatus CRefTable::RemoveNodeRef ( uInt32 inNodeRef,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->RemoveRef( inNodeRef, eNodeRefType, inPID, inIPAddress, true );
}
return( siResult );
}
tDirStatus CRefTable::RemoveRecordRef ( uInt32 inRecRef,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->RemoveRef( inRecRef, eRecordRefType, inPID, inIPAddress, true );
}
return( siResult );
}
tDirStatus CRefTable::RemoveAttrListRef ( uInt32 inAttrListRef,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->RemoveRef( inAttrListRef, eAttrListRefType, inPID, inIPAddress, true );
}
return( siResult );
}
tDirStatus CRefTable::RemoveAttrValueRef ( uInt32 inAttrValueRef,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->RemoveRef( inAttrValueRef, eAttrValueListRefType, inPID, inIPAddress, true );
}
return( siResult );
}
tDirStatus CRefTable::SetNodePluginPtr ( tDirNodeReference inNodeRef,
CServerPlugin *inPlugin )
{
tDirStatus siResult = eDSDirSrvcNotOpened;
if ( gRefTable != nil )
{
siResult = gRefTable->SetPluginPtr( inNodeRef, eNodeRefType, inPlugin );
}
return( siResult );
}
sRefEntry* CRefTable::GetTableRef ( uInt32 inRefNum )
{
uInt32 uiSlot = 0;
uInt32 uiRefNum = (inRefNum & 0x00FFFFFF);
uInt32 uiTableNum = (inRefNum & 0xFF000000) >> 24;
sRefTable *pTable = nil;
sRefEntry *pOutEntry = nil;
fTableMutex.Wait();
try
{
pTable = GetThisTable( uiTableNum );
if ( pTable == nil ) throw( (sInt32)eDSInvalidReference );
uiSlot = uiRefNum % kMaxTableItems;
if ( pTable->fTableData != nil)
{
if ( pTable->fTableData[ uiSlot ] != nil )
{
if ( uiRefNum == pTable->fTableData[ uiSlot ]->fRefNum )
{
pOutEntry = pTable->fTableData[ uiSlot ];
}
}
}
}
catch( sInt32 err )
{
DBGLOG2( kLogAssert, "Reference %l error = %l", inRefNum, err );
}
fTableMutex.Signal();
return( pOutEntry );
}
sRefTable* CRefTable::GetNextTable ( sRefTable *inTable )
{
uInt32 uiTblNum = 0;
sRefTable *pOutTable = nil;
fTableMutex.Wait();
try
{
if ( inTable == nil )
{
if ( fRefTables[ 1 ] == nil )
{
fRefTables[ 1 ] = (sRefTable *)::calloc( sizeof( sRefTable ), sizeof( char ) );
if ( fRefTables[ 1 ] == nil ) throw((sInt32)eMemoryAllocError);
fRefTables[ 1 ]->fTableNum = 1;
fTableCount = 1;
}
pOutTable = fRefTables[ 1 ];
}
else
{
uiTblNum = inTable->fTableNum + 1;
if (uiTblNum > kMaxTables) throw( (sInt32)eDSInvalidReference );
if ( fRefTables[ uiTblNum ] == nil )
{
fTableCount = uiTblNum;
fRefTables[ uiTblNum ] = (sRefTable *)::calloc( sizeof( sRefTable ), sizeof( char ) );
if ( fRefTables[ uiTblNum ] == nil ) throw((sInt32)eMemoryAllocError);
if (uiTblNum == 0) throw( (sInt32)eDSInvalidReference );
fRefTables[ uiTblNum ]->fTableNum = uiTblNum;
}
pOutTable = fRefTables[ uiTblNum ];
}
}
catch( sInt32 err )
{
DBGLOG1( kLogAssert, "Reference table error = %l", err );
}
fTableMutex.Signal();
return( pOutTable );
}
sRefTable* CRefTable::GetThisTable ( uInt32 inTableNum )
{
sRefTable *pOutTable = nil;
fTableMutex.Wait();
pOutTable = fRefTables[ inTableNum ];
fTableMutex.Signal();
return( pOutTable );
}
tDirStatus CRefTable::GetNewRef ( uInt32 *outRef,
uInt32 inParentID,
eRefTypes inType,
CServerPlugin *inPlugin,
sInt32 inPID,
uInt32 inIPAddress )
{
bool done = false;
tDirStatus outResult = eDSNoErr;
sRefTable *pCurTable = nil;
uInt32 uiRefNum = 0;
uInt32 uiCntr = 0;
uInt32 uiSlot = 0;
uInt32 uiTableNum = 0;
uInt32 refCountUpdate = 0;
fTableMutex.Wait();
try
{
*outRef = 0;
while ( !done )
{
pCurTable = GetNextTable( pCurTable );
if ( pCurTable == nil ) throw( (sInt32)eDSRefTableAllocError );
if ( pCurTable->fItemCnt < kMaxTableItems )
{
uiCntr = 0;
uiTableNum = pCurTable->fTableNum;
while ( (uiCntr < kMaxTableItems) && !done ) {
if ( (pCurTable->fCurRefNum == 0) ||
(pCurTable->fCurRefNum > 0x000FFFFF) )
{
pCurTable->fCurRefNum = 1;
}
uiRefNum = pCurTable->fCurRefNum++;
uiSlot = uiRefNum % kMaxTableItems;
if ( pCurTable->fTableData[ uiSlot ] == nil )
{
pCurTable->fTableData[ uiSlot ] = (sRefEntry *)::calloc( sizeof( sRefEntry ), sizeof( char ) );
if ( pCurTable->fTableData[ uiSlot ] == nil ) throw( (sInt32)eDSRefTableAllocError );
pCurTable->fTableData[ uiSlot ]->fRefNum = uiRefNum;
pCurTable->fTableData[ uiSlot ]->fType = inType;
pCurTable->fTableData[ uiSlot ]->fParentID = inParentID;
pCurTable->fTableData[ uiSlot ]->fPID = inPID;
pCurTable->fTableData[ uiSlot ]->fIPAddress = inIPAddress;
pCurTable->fTableData[ uiSlot ]->fPlugin = inPlugin;
pCurTable->fTableData[ uiSlot ]->fChildren = nil;
pCurTable->fTableData[ uiSlot ]->fChildPID = nil;
uiTableNum = (uiTableNum << 24);
uiRefNum = uiRefNum | uiTableNum;
*outRef = uiRefNum;
pCurTable->fItemCnt++;
outResult = eDSNoErr;
done = true;
if (inType == eDirectoryRefType)
{
refCountUpdate = UpdateClientPIDRefCount(inPID, inIPAddress, true, uiRefNum);
}
else
{
refCountUpdate = UpdateClientPIDRefCount(inPID, inIPAddress, true);
}
}
uiCntr++; }
}
}
if ( inParentID != 0 )
{
outResult = LinkToParent( *outRef, inType, inParentID, inPID, inIPAddress );
}
}
catch( sInt32 err )
{
outResult = (tDirStatus)err;
}
fTableMutex.Signal();
return( outResult );
}
tDirStatus CRefTable::LinkToParent ( uInt32 inRefNum,
uInt32 inType,
uInt32 inParentID,
sInt32 inPID,
uInt32 inIPAddress )
{
tDirStatus dsResult = eDSNoErr;
sRefEntry *pCurrRef = nil;
sListInfo *pChildInfo = nil;
fTableMutex.Wait();
try
{
pCurrRef = GetTableRef( inParentID );
if ( pCurrRef == nil ) throw( (sInt32)eDSInvalidReference );
pChildInfo = (sListInfo *)::calloc( sizeof( sListInfo ), sizeof( char ) );
if ( pChildInfo == nil ) throw( (sInt32)eDSRefTableAllocError );
pChildInfo->fRefNum = inRefNum;
pChildInfo->fType = inType;
pChildInfo->fPID = inPID;
pChildInfo->fIPAddress = inIPAddress;
pChildInfo->fNext = pCurrRef->fChildren;
pCurrRef->fChildren = pChildInfo;
}
catch( sInt32 err )
{
dsResult = (tDirStatus)err;
}
fTableMutex.Signal();
return( dsResult );
}
tDirStatus CRefTable::UnlinkFromParent ( uInt32 inRefNum )
{
tDirStatus dsResult = eDSNoErr;
uInt32 i = 1;
uInt32 parentID = 0;
sRefEntry *pCurrRef = nil;
sRefEntry *pParentRef = nil;
sListInfo *pCurrChild = nil;
sListInfo *pPrevChild = nil;
fTableMutex.Wait();
try
{
pCurrRef = GetTableRef( inRefNum );
if ( pCurrRef == nil ) throw( (sInt32)eDSInvalidReference );
parentID = pCurrRef->fParentID;
if ( parentID != 0 )
{
pParentRef = GetTableRef( parentID );
if ( pParentRef == nil ) throw( (sInt32)eDSInvalidReference );
pCurrChild = pParentRef->fChildren;
pPrevChild = pParentRef->fChildren;
while ( pCurrChild != nil )
{
if ( pCurrChild->fRefNum == inRefNum )
{
if ( i == 1 )
{
pParentRef->fChildren = pCurrChild->fNext;
}
else
{
pPrevChild->fNext = pCurrChild->fNext;
}
free( pCurrChild );
pCurrChild = nil;
break;
}
pPrevChild = pCurrChild;
pCurrChild = pCurrChild->fNext;
i++;
}
}
}
catch( sInt32 err )
{
dsResult = (tDirStatus)err;
}
fTableMutex.Signal();
return( dsResult );
}
tDirStatus CRefTable::GetReference ( uInt32 inRefNum, sRefEntry **outRefData )
{
tDirStatus dsResult = eDSNoErr;
sRefEntry *pCurrRef = nil;
fTableMutex.Wait();
try
{
pCurrRef = GetTableRef( inRefNum );
if ( pCurrRef == nil )
{
DBGLOG1( kLogHandler, "Given reference value of <%u> has no valid reference table entry.", inRefNum);
throw( (sInt32)eDSInvalidReference );
}
*outRefData = pCurrRef;
}
catch( sInt32 err )
{
dsResult = (tDirStatus)err;
}
fTableMutex.Signal();
return( dsResult );
}
tDirStatus CRefTable::RemoveRef ( uInt32 inRefNum,
uInt32 inType,
sInt32 inPID,
uInt32 inIPAddress,
bool inbAtTop)
{
tDirStatus dsResult = eDSNoErr;
sRefEntry *pCurrRef = nil;
sRefTable *pTable = nil;
uInt32 uiSlot = 0;
uInt32 uiTableNum = (inRefNum & 0xFF000000) >> 24;
uInt32 uiRefNum = (inRefNum & 0x00FFFFFF);
bool doFree = false;
sPIDInfo *pPIDInfo = nil;
sPIDInfo *pPrevPIDInfo = nil;
uInt32 refCountUpdate = 0;
sRefCleanUpEntry *aRefCleanUpEntries = nil;
sRefCleanUpEntry *aRefCleanUpEntriesIter = nil;
sInt32 deallocResult = eDSNoErr;
fTableMutex.Wait();
try
{
dsResult = VerifyReference( inRefNum, inType, nil, inPID, inIPAddress );
if ( dsResult == eDSNoErr )
{
pTable = GetThisTable( uiTableNum );
if ( pTable == nil ) throw( (sInt32)eDSInvalidReference );
uiSlot = uiRefNum % kMaxTableItems;
if ( inType != eDirectoryRefType ) {
dsResult = UnlinkFromParent( inRefNum );
if ( dsResult != eDSNoErr ) throw( (sInt32)dsResult );
}
pCurrRef = GetTableRef( inRefNum ); if ( pCurrRef == nil ) throw( (sInt32)eDSInvalidReference );
if (inType != pCurrRef->fType) throw( (sInt32)eDSInvalidReference );
if ( pCurrRef->fChildren != nil )
{
RemoveChildren( pCurrRef->fChildren, inPID, inIPAddress );
}
if ( (pCurrRef->fPID == inPID) && (pCurrRef->fIPAddress == inIPAddress) )
{
pCurrRef->fPID = -1;
if (pCurrRef->fChildPID == nil)
{
doFree = true;
}
}
else
{
pPIDInfo = pCurrRef->fChildPID;
pPrevPIDInfo = pCurrRef->fChildPID;
while (pPIDInfo != nil)
{
if ( (pPIDInfo->fPID == inPID) && (pPIDInfo->fIPAddress == inIPAddress) )
{
if (pPIDInfo == pCurrRef->fChildPID)
{
pCurrRef->fChildPID = pCurrRef->fChildPID->fNext;
free(pPIDInfo);
pPIDInfo = pCurrRef->fChildPID;
pPrevPIDInfo = pCurrRef->fChildPID;
}
else
{
pPrevPIDInfo->fNext = pPIDInfo->fNext;
free(pPIDInfo);
pPIDInfo = pPrevPIDInfo->fNext;
}
}
else
{
pPrevPIDInfo = pPIDInfo;
pPIDInfo = pPIDInfo->fNext;
}
}
if ( (pCurrRef->fPID == -1) && (pCurrRef->fChildPID == nil) )
{
doFree = true;
}
}
if (doFree)
{
if ( pTable->fTableData[ uiSlot ] != nil )
{
if ( uiRefNum == pTable->fTableData[ uiSlot ]->fRefNum )
{
pCurrRef = pTable->fTableData[ uiSlot ];
pTable->fTableData[ uiSlot ] = nil;
pTable->fItemCnt--;
if (inType == eDirectoryRefType)
{
refCountUpdate = UpdateClientPIDRefCount(inPID, inIPAddress, false, inRefNum);
}
else
{
refCountUpdate = UpdateClientPIDRefCount(inPID, inIPAddress, false);
}
if (fDeallocProc != nil)
{
if (fRefCleanUpEntriesHead == nil)
{
fRefCleanUpEntriesHead = (sRefCleanUpEntry *)calloc(1, sizeof(sRefCleanUpEntry));
fRefCleanUpEntriesHead->fRefNum = inRefNum; fRefCleanUpEntriesHead->fType = pCurrRef->fType;
fRefCleanUpEntriesHead->fPlugin = pCurrRef->fPlugin;
fRefCleanUpEntriesHead->fNext = nil;
fRefCleanUpEntriesTail = fRefCleanUpEntriesHead;
}
else
{
fRefCleanUpEntriesTail->fNext = (sRefCleanUpEntry *)calloc(1, sizeof(sRefCleanUpEntry));
fRefCleanUpEntriesTail->fNext->fRefNum = inRefNum; fRefCleanUpEntriesTail->fNext->fType = pCurrRef->fType;
fRefCleanUpEntriesTail->fNext->fPlugin = pCurrRef->fPlugin;
fRefCleanUpEntriesTail->fNext->fNext = nil;
fRefCleanUpEntriesTail = fRefCleanUpEntriesTail->fNext;
}
}
free(pCurrRef);
pCurrRef = nil;
}
}
}
}
}
catch( sInt32 err )
{
dsResult = (tDirStatus)err;
}
if (inbAtTop) {
aRefCleanUpEntriesIter = fRefCleanUpEntriesHead;
fRefCleanUpEntriesHead = nil;
fRefCleanUpEntriesTail = nil;
}
fTableMutex.Signal();
if (inbAtTop) {
while (aRefCleanUpEntriesIter != nil)
{
aRefCleanUpEntries = aRefCleanUpEntriesIter;
if (aRefCleanUpEntries->fPlugin != nil)
{
deallocResult = (tDirStatus)(*fDeallocProc)( aRefCleanUpEntries->fRefNum, aRefCleanUpEntries->fType, aRefCleanUpEntries->fPlugin );
}
aRefCleanUpEntriesIter = aRefCleanUpEntries->fNext;
free(aRefCleanUpEntries);
}
}
return( dsResult );
}
void CRefTable::RemoveChildren ( sListInfo *inChildList,
sInt32 inPID,
uInt32 inIPAddress )
{
sListInfo *pCurrChild = nil;
sListInfo *pNextChild = nil;
fTableMutex.Wait();
try
{
pCurrChild = inChildList;
while ( pCurrChild != nil )
{
pNextChild = pCurrChild->fNext;
if ( ( pCurrChild->fPID == inPID ) && ( pCurrChild->fIPAddress == inIPAddress ) )
{
RemoveRef( pCurrChild->fRefNum, pCurrChild->fType, inPID, inIPAddress, false );
}
pCurrChild = pNextChild;
}
}
catch( sInt32 err )
{
}
fTableMutex.Signal();
}
tDirStatus CRefTable::SetPluginPtr ( uInt32 inRefNum, uInt32 inType, CServerPlugin *inPlugin )
{
tDirStatus dsResult = eDSNoErr;
sRefEntry *pCurrRef = nil;
fTableMutex.Wait();
try
{
pCurrRef = GetTableRef( inRefNum );
if ( pCurrRef == nil ) throw( (sInt32)eDSInvalidReference );
if (inType != pCurrRef->fType) throw( (sInt32)eDSInvalidReference );
pCurrRef->fPlugin = inPlugin;
}
catch( sInt32 err )
{
}
fTableMutex.Signal();
return( dsResult );
}
tDirStatus CRefTable:: AddChildPIDToRef ( uInt32 inRefNum, uInt32 inParentPID, sInt32 inChildPID, uInt32 inIPAddress )
{
tDirStatus dsResult = eDSNoErr;
sRefEntry *pCurrRef = nil;
sPIDInfo *pChildPIDInfo = nil;
gRefTable->Lock();
try
{
dsResult = gRefTable->VerifyReference( inRefNum, eNodeRefType, nil, inParentPID, inIPAddress );
if ( dsResult != eDSNoErr ) throw( (sInt32)dsResult );
pCurrRef = gRefTable->GetTableRef( inRefNum );
if ( pCurrRef == nil ) throw( (sInt32)eDSInvalidReference );
pChildPIDInfo = (sPIDInfo *)::calloc( 1, sizeof( sPIDInfo ) );
if ( pChildPIDInfo == nil ) throw( (sInt32)eDSRefTableAllocError );
pChildPIDInfo->fPID = inChildPID;
pChildPIDInfo->fIPAddress = inIPAddress;
pChildPIDInfo->fNext = pCurrRef->fChildPID;
pCurrRef->fChildPID = pChildPIDInfo;
}
catch( sInt32 err )
{
dsResult = (tDirStatus)err;
}
gRefTable->Unlock();
return( dsResult );
}
uInt32 CRefTable:: UpdateClientPIDRefCount ( sInt32 inClientPID, uInt32 inIPAddress, bool inUpRefCount, uInt32 inDirRef )
{
uInt32 aCount = 0;
fClientPIDListLock->Wait();
try
{
if ( inDirRef != 0 )
{
tIPPIDDirRefMap::iterator aIPentry = fClientDirRefMap.find( inIPAddress );
if( aIPentry != fClientDirRefMap.end() )
{
tPIDDirRefMap::iterator aPIDentry = aIPentry->second.find( inClientPID );
if( aPIDentry != aIPentry->second.end() )
{
if( inUpRefCount )
{
aPIDentry->second.insert( inDirRef ); }
else
{
aPIDentry->second.erase( inDirRef ); }
}
else {
tDirRefSet newSet;
newSet.insert( inDirRef ); aIPentry->second[inClientPID] = newSet; }
}
else {
tDirRefSet newSet;
tPIDDirRefMap aPIDentry;
newSet.insert( inDirRef ); aPIDentry[inClientPID] = newSet; fClientDirRefMap[inIPAddress] = aPIDentry; }
}
tIPPIDRefCountMap::iterator aIPrefentry = fClientRefCountMap.find( inIPAddress );
if( aIPrefentry != fClientRefCountMap.end() )
{
tPIDRefCountMap::iterator aPIDentry = aIPrefentry->second.find( inClientPID );
if( aPIDentry != aIPrefentry->second.end() )
{
if (inUpRefCount)
{
aPIDentry->second += 1;
aCount = aPIDentry->second;
if ( (aCount > gRefCountWarningLimit) && !(aCount % 25) )
{
syslog(LOG_ALERT,"Potential VM growth in DirectoryService since client PID: %d, has %d open references when the warning limit is %d.", inClientPID, aCount, gRefCountWarningLimit);
DBGLOG3( kLogHandler, "Potential VM growth in DirectoryService since client PID: %d, has %d open references when the warning limit is %d.", inClientPID, aCount, gRefCountWarningLimit);
}
else if (gLogAPICalls)
{
syslog(LOG_ALERT,"Client PID: %d, has %d open references.", inClientPID, aCount);
}
}
else
{
aPIDentry->second -= 1;
aCount = aPIDentry->second;
if (gLogAPICalls)
{
syslog(LOG_ALERT,"Client PID: %d, has %d open references.", inClientPID, aCount);
}
}
if( aCount == 0 )
{
tIPPIDDirRefMap::iterator aIPentry = fClientDirRefMap.find( inIPAddress );
if( aIPentry != fClientDirRefMap.end() )
{
aIPentry->second.erase( inClientPID );
}
aIPrefentry->second.erase( aPIDentry );
}
}
else {
aIPrefentry->second[ inClientPID ] = 1;
aCount = 1;
}
}
else if( inUpRefCount ) {
tPIDRefCountMap newMap;
newMap[inClientPID] = 1;
fClientRefCountMap[ inIPAddress ] = newMap;
aCount = 1;
}
}
catch( ... )
{
}
fClientPIDListLock->Signal();
return aCount;
}
void CRefTable::CleanClientRefs ( uInt32 inIPAddress, uInt32 inPIDorPort )
{
if (gRefTable != nil)
{
gRefTable->DoCleanClientRefs(inIPAddress, inPIDorPort);
}
}
void CRefTable::DoCleanClientRefs ( uInt32 inIPAddress, uInt32 inPIDorPort )
{
tDirRefSet cleanupSet;
if (fClientPIDListLock->Wait(1) != eDSNoErr)
{
fClientPIDListLock->Signal(); return;
}
try
{
tIPPIDDirRefMap::iterator aIPentry = fClientDirRefMap.find( inIPAddress );
if( aIPentry != fClientDirRefMap.end() )
{
tPIDDirRefMap::iterator aPIDentry = aIPentry->second.find( inPIDorPort );
if( aPIDentry != aIPentry->second.end() )
{
cleanupSet = aPIDentry->second;
}
}
tIPPIDRefCountMap::iterator aIPrefentry = fClientRefCountMap.find( inIPAddress );
if( aIPrefentry != fClientRefCountMap.end() )
{
tPIDRefCountMap::iterator aPIDentry = aIPrefentry->second.find( inPIDorPort );
if( aPIDentry != aIPrefentry->second.end() )
{
if (gLogAPICalls)
{
syslog(LOG_ALERT,"Client PID: %d, had %d open references before cleanup.",inPIDorPort, aPIDentry->second);
}
DBGLOG2( kLogHandler, "Client PID: %d, had %d open references before cleanup.", inPIDorPort, aPIDentry->second );
}
}
if (gLogAPICalls)
{
aIPentry = fClientDirRefMap.begin();
while( aIPentry != fClientDirRefMap.end() )
{
tPIDDirRefMap::iterator aPIDentry = aIPentry->second.begin();
while( aPIDentry != aIPentry->second.end() )
{
if( aPIDentry->first != inPIDorPort )
{
syslog( LOG_ALERT, "Client PID: %d, has %d open references in table.", aPIDentry->first, aPIDentry->second.size() );
}
++aPIDentry;
}
++aIPentry;
}
}
}
catch( ... )
{
}
fClientPIDListLock->Signal();
try
{
tDirRefSet::iterator aIterator = cleanupSet.begin();
while( aIterator != cleanupSet.end() )
{
CRefTable::RemoveDirRef( *aIterator, inPIDorPort, inIPAddress );
++aIterator;
}
}
catch( ... )
{
}
}