249 lines
6.3 KiB
C
249 lines
6.3 KiB
C
#include "convlog.h"
|
||
|
||
/*
|
||
This File implements caching of the mappings between ip addresses and machine names.
|
||
|
||
|
||
pHashTable: An array of linked list headers which map directly to hash values, eg. the mapping for
|
||
an ipaddr is stored in the list with header pHashTable[GetHashVal(ipaddr)]
|
||
|
||
pHashEntries: An array of HashEntry strucures. Each structure contains a mapping of ip address to machine name.
|
||
|
||
Algorithm: A HashEntry structure is allocated each time an
|
||
entry is added to the cache. These are reused in circular fashion, eg. pHashEntries[0] is used first,
|
||
then pHashEntries[1], etc. When the ulNumHashEntries+1 entry is added to the cache, the entry currently
|
||
in pHashEntries[0] is discarded and pHashEntries[0] is reused. Hence the discard mechanism is
|
||
Least Recently Allocated. This is probably not as efficient as Least Recently Used in terms of keeping
|
||
the most relevant entries in the cache. But it is more effiecient in terms of code speed, as there is no overhead
|
||
for keeping usage statistics or finding the least recently used entry.
|
||
|
||
All linked lists are kept in the reverse order of their allocation, that is, the most recently allocated is at the start
|
||
of the list. This allows for the most efficient allocation. It "should" also be efficient for lookup, but that could vary
|
||
on a per logfile basis.
|
||
|
||
All addressing of the pHashEntries array is currently done via array indices. At some point this should probably be
|
||
converted to use structure pointers, as that generates slightly more efficient code.
|
||
*/
|
||
|
||
#define HASHTABLELEN 2048
|
||
|
||
#define NOCACHEENTRY 0xFFFFFFFF
|
||
|
||
#define GetHashVal(p) ((p) % HASHTABLELEN)
|
||
|
||
//This gets rid of the byte ordering dependency
|
||
#define BINARYIPTONUMERICIP(p1) (ULONG) (((ULONG)p1[0] << 24) + ((ULONG)p1[1] << 16) + ((ULONG)p1[2] << 8) + ((ULONG)p1[3]))
|
||
|
||
ULONG HashTable[HASHTABLELEN] = {0};
|
||
|
||
PHASHENTRY pHashEntries;
|
||
|
||
ULONG ulFreeListIndex = 0;
|
||
|
||
BOOL bFreeElements = TRUE;
|
||
|
||
BOOL bCachingEnabled = FALSE;
|
||
|
||
ULONG ulCacheHits = 0;
|
||
ULONG ulCacheMisses = 0;
|
||
|
||
ULONG ulNumHashEntries;
|
||
|
||
|
||
VOID
|
||
InitHashTable(
|
||
DWORD ulCacheSize
|
||
)
|
||
{
|
||
DWORD i;
|
||
|
||
for (i = 0; i < HASHTABLELEN; i++) {
|
||
HashTable[i] = NOCACHEENTRY;
|
||
}
|
||
|
||
ulNumHashEntries = ulCacheSize;
|
||
while ((!bCachingEnabled) && (ulNumHashEntries >= 1000)) {
|
||
|
||
pHashEntries = (PHASHENTRY)
|
||
GlobalAlloc(GPTR, (sizeof(HASHENTRY) * ulNumHashEntries));
|
||
|
||
if (NULL != pHashEntries) {
|
||
bCachingEnabled = TRUE;
|
||
} else {
|
||
ulNumHashEntries /= 2;
|
||
}
|
||
}
|
||
|
||
if (!bCachingEnabled) {
|
||
printfids(IDS_CACHE_ERR);
|
||
}
|
||
|
||
} // InitHashTable
|
||
|
||
|
||
ULONG
|
||
AllocHashEntry(
|
||
VOID
|
||
)
|
||
{
|
||
ULONG i, ulCurHashVal;
|
||
if (ulFreeListIndex == ulNumHashEntries) {
|
||
ulFreeListIndex = 0;
|
||
bFreeElements = FALSE;
|
||
}
|
||
if (!bFreeElements) { // Use this entry anyway, but free it first
|
||
ulCurHashVal = GetHashVal(pHashEntries[ulFreeListIndex].uIPAddr); //find hashtable entry
|
||
if (HashTable[ulCurHashVal] == ulFreeListIndex) {
|
||
HashTable[ulCurHashVal] = pHashEntries[ulFreeListIndex].NextPtr; //Remove the entry from the table
|
||
}
|
||
else {
|
||
for (i = HashTable[ulCurHashVal]; pHashEntries[i].NextPtr != ulFreeListIndex; i = pHashEntries[i].NextPtr)
|
||
;
|
||
pHashEntries[i].NextPtr = pHashEntries[ulFreeListIndex].NextPtr; //Remove the entry from the table
|
||
}
|
||
}
|
||
|
||
return(ulFreeListIndex++);
|
||
}
|
||
|
||
ULONG GetElementFromCache(ULONG uIPAddr) {
|
||
ULONG i = GetHashVal(uIPAddr);
|
||
|
||
for (i =HashTable[i];(i != NOCACHEENTRY)&&(pHashEntries[i].uIPAddr != uIPAddr);i = pHashEntries[i].NextPtr)
|
||
;
|
||
return(i);
|
||
}
|
||
|
||
VOID
|
||
AddEntryToCache(
|
||
IN ULONG uIPAddr,
|
||
IN PCHAR szMachineName
|
||
)
|
||
{
|
||
ULONG uHashEntry;
|
||
ULONG uHashVal;
|
||
char *szTemp;
|
||
|
||
uHashEntry=AllocHashEntry();
|
||
uHashVal=GetHashVal(uIPAddr);
|
||
|
||
pHashEntries[uHashEntry].uIPAddr = uIPAddr;
|
||
if (strlen(szMachineName) < MAXMACHINELEN)
|
||
szTemp = strcpy(pHashEntries[uHashEntry].szMachineName,szMachineName);
|
||
else {
|
||
szTemp = strncpy(pHashEntries[uHashEntry].szMachineName,szMachineName, (size_t)MAXMACHINELEN);
|
||
pHashEntries[uHashEntry].szMachineName[MAXMACHINELEN - 1] = '\0';
|
||
}
|
||
pHashEntries[uHashEntry].NextPtr=HashTable[uHashVal];
|
||
HashTable[uHashVal] = uHashEntry;
|
||
}
|
||
|
||
VOID
|
||
AddLocalMachineToCache(
|
||
VOID
|
||
)
|
||
{
|
||
|
||
INT err;
|
||
CHAR nameBuf[MAX_PATH+1];
|
||
PHOSTENT hostent;
|
||
|
||
err = gethostname( nameBuf, sizeof(nameBuf));
|
||
|
||
if ( err != 0 ) {
|
||
return;
|
||
}
|
||
|
||
hostent = gethostbyname( nameBuf );
|
||
if ( hostent == NULL ) {
|
||
return;
|
||
}
|
||
|
||
AddEntryToCache(
|
||
((PIN_ADDR)hostent->h_addr_list[0])->s_addr,
|
||
hostent->h_name
|
||
);
|
||
return;
|
||
|
||
} // AddLocalMachineToCache
|
||
|
||
|
||
PCHAR
|
||
GetMachineName(
|
||
IN PCHAR szClientIP
|
||
)
|
||
{
|
||
IN_ADDR inaddr;
|
||
PHOSTENT lpHostEnt;
|
||
ULONG ulNumericIP;
|
||
ULONG ulCurHashIndex;
|
||
CHAR tmpIP[64];
|
||
PCHAR szReturnString = szClientIP;
|
||
|
||
strcpy(tmpIP,szClientIP);
|
||
FindChar(tmpIP,',');
|
||
|
||
inaddr.s_addr = inet_addr(tmpIP);
|
||
|
||
//
|
||
// invalid IP
|
||
//
|
||
|
||
if ( inaddr.s_addr == INADDR_NONE ) {
|
||
goto exit;
|
||
}
|
||
|
||
if (bCachingEnabled) {
|
||
|
||
ulNumericIP = inaddr.s_addr;
|
||
if ((ulCurHashIndex=GetElementFromCache(ulNumericIP)) == NOCACHEENTRY) {
|
||
|
||
lpHostEnt = gethostbyaddr(
|
||
(char *)&inaddr, (int)4, (int)PF_INET);
|
||
|
||
if (lpHostEnt != NULL) {
|
||
szReturnString = lpHostEnt->h_name;
|
||
}
|
||
|
||
AddEntryToCache(ulNumericIP,szReturnString);
|
||
ulCacheMisses++;
|
||
} else { //Entry is in cache
|
||
szReturnString=pHashEntries[ulCurHashIndex].szMachineName;
|
||
ulCacheHits++;
|
||
}
|
||
|
||
} else { //Caching not enabled
|
||
|
||
lpHostEnt = gethostbyaddr((char *)&inaddr, (int) 4, (int) PF_INET);
|
||
if (lpHostEnt != NULL) {
|
||
szReturnString = lpHostEnt->h_name;
|
||
}
|
||
}
|
||
exit:
|
||
return(szReturnString);
|
||
}
|
||
|
||
|
||
#if DBG
|
||
VOID
|
||
PrintCacheTotals()
|
||
{
|
||
if (bCachingEnabled) {
|
||
|
||
DWORD dwTotal = ulCacheHits + ulCacheMisses;
|
||
double dRatio;
|
||
|
||
if ( ulCacheHits != 0 ) {
|
||
dRatio = (double)ulCacheHits/(double)dwTotal;
|
||
} else {
|
||
dRatio = 0;
|
||
}
|
||
|
||
printfids(IDS_CACHE_HITS, ulCacheHits);
|
||
printfids(IDS_CACHE_MISS, ulCacheMisses);
|
||
printfids(IDS_CACHE_TOT, dRatio);
|
||
}
|
||
}
|
||
#endif
|
||
|