// // MODULE: APGTSCAC.CPP // // PURPOSE: Belief network caching support classes // Fully implements class CBNCacheItem // Fully implements class CBNCache // // PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint // // COMPANY: Saltmine Creative, Inc. (206)-284-7511 support@saltmine.com // // AUTHOR: Joe Mabel, modeled on earlier work by Roman Mach // // ORIGINAL DATE: 10-2-96, completely rewritten 8/98 // // NOTES: // 1. The strategy here builds a "Most-recently-used" cache (singly-linked list of // CBNCacheItem ordered by how recently used) // 2. Although you are first supposed to call FindCacheItem and only call AddCacheItem // if that fails, there is no support to do this in a threadsafe manner, so there // had better be only one thread with access to a given CCache. Mutex protection // must come at a higher level. // 3. One cache is associated with each [instance of a] Belief Network // // Version Date By Comments //-------------------------------------------------------------------- // V0.1 - RM Original // V3.0 8/7/98 JM Original // #include "stdafx.h" #include "event.h" #include "apgtscac.h" #include "baseexception.h" #include "CharConv.h" #include // The CCacheItem comparison operators depend on the assumption that if the cache key // is identical, the cache value will be, too. bool CCacheItem::operator== (const CCacheItem &item) const { return (BasisForInference == item.BasisForInference); } bool CCacheItem::operator!= (const CCacheItem &item) const { return (BasisForInference != item.BasisForInference); } // Note that this is not lexicographical order. We're saying any shorter // cache key compares as less than any longer. bool CCacheItem::operator< (const CCacheItem &item) const { const CBasisForInference::size_type thisSize = BasisForInference.size(); const CBasisForInference::size_type otherSize = item.BasisForInference.size(); if (thisSize < otherSize) return true; if (thisSize > otherSize) return false; // same length, use lexicographical order. return (BasisForInference < item.BasisForInference); } // Note that this is not lexicographical order. We're saying any longer // cache key compares as greater than any shorter. bool CCacheItem::operator> (const CCacheItem &item) const { const CBasisForInference::size_type thisSize = BasisForInference.size(); const CBasisForInference::size_type otherSize = item.BasisForInference.size(); if (thisSize > otherSize) return true; if (thisSize < otherSize) return false; // same length, use lexicographical order. return (BasisForInference > item.BasisForInference); } // NOTE: Must call FindCacheItem first and not call this // function to prevent duplicate records from going into cache bool CCache::AddCacheItem( const CBasisForInference &BasisForInference, const CRecommendations &Recommendations) { if (GetCount() >= MAXCACHESIZE) listItems.pop_back(); try { CCacheItem item(BasisForInference, Recommendations); listItems.push_front(item); if (listItems.size() >= k_CacheSizeMax) listItems.pop_back(); return true; // always succeeds } catch (exception& x) { CString str; // Note STL exception in event log. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ ); CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(), SrcLoc.GetSrcFileLineStr(), CCharConversion::ConvertACharToString(x.what(), str), _T(""), EV_GTS_STL_EXCEPTION ); return( false ); } } bool CCache::FindCacheItem( const CBasisForInference &BasisForInference, CRecommendations &Recommendations /* output */) const { Recommendations.clear(); CCacheItem item(BasisForInference, Recommendations /* effectively, a dummy */ ); const list::const_iterator itBegin = listItems.begin(); const list::const_iterator itEnd = listItems.end(); const list::const_iterator itMatch = find(itBegin, itEnd, item); if (itMatch == itEnd) return false; Recommendations = itMatch->GetRecommendations(); return true; } UINT CCache::GetCount() const { return listItems.size(); }