213 lines
4.6 KiB
C++
213 lines
4.6 KiB
C++
|
//
|
||
|
// MODULE: APGTSCAC.CPP
|
||
|
//
|
||
|
// PURPOSE: Belief network caching support classes
|
||
|
// Each CBNCacheItem object effectively corresponds to a possible state of the belief
|
||
|
// network, and provides a next recommended action. More specifically, data member
|
||
|
// m_CItem provides
|
||
|
// - an array of nodes and a corresponding array of their states. Taken together,
|
||
|
// these represent a state of the network
|
||
|
// - an array of nodes, which constitute the recommendations as to what to try next
|
||
|
// based on this state of the network. The first node in the list is the node we
|
||
|
// will display; if the user says "don't want to try this now" we'd go on to the next,
|
||
|
// etc.
|
||
|
// These are collected into a CBNCache object, so if you get a hit on one of these network
|
||
|
// states, you can get your recommendation without needing the overhead of hitting BNTS.
|
||
|
//
|
||
|
// PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint
|
||
|
//
|
||
|
// COMPANY: Saltmine Creative, Inc. (206)-633-4743 support@saltmine.com
|
||
|
//
|
||
|
// AUTHOR: Roman Mach
|
||
|
//
|
||
|
// ORIGINAL DATE: 10-2-96
|
||
|
//
|
||
|
// NOTES:
|
||
|
//
|
||
|
// Version Date By Comments
|
||
|
//--------------------------------------------------------------------
|
||
|
// V0.1 - RM Original
|
||
|
// V0.2 6/4/97 RWM Local Version for Memphis
|
||
|
// V0.3 04/09/98 JM/OK+ Local Version for NT5
|
||
|
//
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "apgts.h"
|
||
|
#include "ErrorEnums.h"
|
||
|
//
|
||
|
//
|
||
|
CBNCacheItem::CBNCacheItem(const BN_CACHE_ITEM *pItem, CBNCacheItem* pcitNext)
|
||
|
{
|
||
|
m_dwErr = 0;
|
||
|
|
||
|
memcpy(&m_CItem, pItem, sizeof (BN_CACHE_ITEM));
|
||
|
|
||
|
m_CItem.uName = (UINT *)malloc(m_CItem.uNodeCount * sizeof (UINT));
|
||
|
m_CItem.uValue = (UINT *)malloc(m_CItem.uNodeCount * sizeof (UINT));
|
||
|
m_CItem.uRec = (UINT *)malloc(m_CItem.uRecCount * sizeof (UINT));
|
||
|
|
||
|
if (m_CItem.uName && m_CItem.uValue && m_CItem.uRec) {
|
||
|
memcpy(m_CItem.uName, pItem->uName, m_CItem.uNodeCount * sizeof (UINT));
|
||
|
memcpy(m_CItem.uValue, pItem->uValue, m_CItem.uNodeCount * sizeof (UINT));
|
||
|
memcpy(m_CItem.uRec, pItem->uRec, m_CItem.uRecCount * sizeof (UINT));
|
||
|
}
|
||
|
else
|
||
|
m_dwErr = EV_GTS_ERROR_CAC_ALLOC_MEM;
|
||
|
|
||
|
m_pcitNext = pcitNext;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
//
|
||
|
CBNCacheItem::~CBNCacheItem()
|
||
|
{
|
||
|
if (m_CItem.uName)
|
||
|
free(m_CItem.uName);
|
||
|
|
||
|
if (m_CItem.uValue)
|
||
|
free(m_CItem.uValue);
|
||
|
|
||
|
if (m_CItem.uRec)
|
||
|
free(m_CItem.uRec);
|
||
|
};
|
||
|
|
||
|
//
|
||
|
//
|
||
|
DWORD CBNCacheItem::GetStatus()
|
||
|
{
|
||
|
return m_dwErr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
//
|
||
|
CBNCache::CBNCache()
|
||
|
{
|
||
|
m_pcit = NULL;
|
||
|
m_dwErr = 0;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
//
|
||
|
CBNCache::~CBNCache()
|
||
|
{
|
||
|
CBNCacheItem *pcit, *pti;
|
||
|
|
||
|
pcit = m_pcit;
|
||
|
while (pcit) {
|
||
|
pti = pcit;
|
||
|
pcit = pcit->m_pcitNext;
|
||
|
delete pti;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
//
|
||
|
DWORD CBNCache::GetStatus()
|
||
|
{
|
||
|
return m_dwErr;
|
||
|
}
|
||
|
|
||
|
// NOTE: Must call FindCacheItem first and not call this
|
||
|
// function to prevent duplicate records from going into cache
|
||
|
//
|
||
|
BOOL CBNCache::AddCacheItem(const BN_CACHE_ITEM *pList)
|
||
|
{
|
||
|
CBNCacheItem *pcit = new CBNCacheItem(pList, m_pcit);
|
||
|
|
||
|
if (pcit == NULL)
|
||
|
m_dwErr = EV_GTS_ERROR_CAC_ALLOC_ITEM;
|
||
|
else if (!m_dwErr)
|
||
|
m_dwErr = pcit->GetStatus();
|
||
|
|
||
|
return (m_pcit = pcit) != NULL;
|
||
|
}
|
||
|
|
||
|
// Find match, return false if not found, otherwise true and fills
|
||
|
// structure with found item
|
||
|
// Also move matched up to top and remove last item if too many
|
||
|
//
|
||
|
BOOL CBNCache::FindCacheItem(const BN_CACHE_ITEM *pList, UINT& count, UINT Name[])
|
||
|
{
|
||
|
UINT uSize;
|
||
|
CBNCacheItem *pcit, *pcitfirst, *pcitlp;
|
||
|
|
||
|
uSize = pList->uNodeCount * sizeof (UINT);
|
||
|
|
||
|
pcitlp = pcitfirst = pcit = m_pcit;
|
||
|
|
||
|
for (; pcit; pcit = pcit->m_pcitNext)
|
||
|
{
|
||
|
if (pList->uNodeCount == pcit->m_CItem.uNodeCount)
|
||
|
{
|
||
|
if (!memcmp(pList->uName, pcit->m_CItem.uName, uSize) &&
|
||
|
!memcmp(pList->uValue, pcit->m_CItem.uValue, uSize))
|
||
|
{
|
||
|
// check not at top already
|
||
|
if (pcit != pcitfirst)
|
||
|
{
|
||
|
// remove from list
|
||
|
while (pcitlp) {
|
||
|
if (pcitlp->m_pcitNext == pcit)
|
||
|
{
|
||
|
pcitlp->m_pcitNext = pcitlp->m_pcitNext->m_pcitNext;
|
||
|
break;
|
||
|
}
|
||
|
pcitlp = pcitlp->m_pcitNext;
|
||
|
}
|
||
|
|
||
|
// move to top
|
||
|
m_pcit = pcit;
|
||
|
pcit->m_pcitNext = pcitfirst;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// count items
|
||
|
if (CountCacheItems() > MAXCACHESIZE)
|
||
|
{
|
||
|
// remove last item
|
||
|
|
||
|
if ((pcitlp = m_pcit) != NULL)
|
||
|
{
|
||
|
if (pcitlp->m_pcitNext)
|
||
|
{
|
||
|
while (pcitlp)
|
||
|
{
|
||
|
if (pcitlp->m_pcitNext->m_pcitNext == NULL)
|
||
|
{
|
||
|
delete pcitlp->m_pcitNext;
|
||
|
pcitlp->m_pcitNext = NULL;
|
||
|
break;
|
||
|
}
|
||
|
pcitlp = pcitlp->m_pcitNext;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pcit == NULL)
|
||
|
return FALSE;
|
||
|
|
||
|
count = pcit->m_CItem.uRecCount;
|
||
|
memcpy(Name, pcit->m_CItem.uRec, count * sizeof (UINT));
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// Get count of items in cache
|
||
|
//
|
||
|
UINT CBNCache::CountCacheItems() const
|
||
|
{
|
||
|
UINT uCount = 0;
|
||
|
|
||
|
for (CBNCacheItem* pcit = m_pcit; pcit; pcit = pcit->m_pcitNext, uCount++)
|
||
|
{
|
||
|
// do nothing: action is all in condition of for-loop
|
||
|
}
|
||
|
|
||
|
return uCount;
|
||
|
}
|
||
|
|