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
|
|||
|
|