//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996 - 1998. // // File: wqcache.hxx // // Contents: WEB Query cache class // // History: 96/Jan/3 DwightKr Created // //---------------------------------------------------------------------------- #pragma once //+--------------------------------------------------------------------------- // // Class: CWQueryBookmark // // Purpose: A bookmark to a specific query // // History: 96/Jan/23 DwightKr Created // //---------------------------------------------------------------------------- const unsigned cchBookmark = (5+16+8+8); // N-xxxx-xxx-xxx class CWQueryBookmark { public: CWQueryBookmark( WCHAR const * wcsBookmark ); CWQueryBookmark( BOOL fSequential, CWQueryItem * pItem, ULONG ulSequenceNumber, LONG lRecordNumber ); BOOL IsSequential() const { return _fSequential; } ULONG GetSequenceNumber() const { return _ulSequenceNumber; } CWQueryItem const * GetQueryItem() const { return _pItem; } LONG GetRecordNumber() const { return _lRecordNumber; } WCHAR const * GetBookmark() const { return _wcsBookmark; } private: BOOL _fSequential; // Is this a sequential cursor CWQueryItem * _pItem; // Address of a query item ULONG _ulSequenceNumber; // Unique sequence number LONG _lRecordNumber; // Record number WCHAR _wcsBookmark[cchBookmark]; // String rep of bookmark }; //+--------------------------------------------------------------------------- // // Class: CWQueryCache // // Purpose: A list of cached queries // // History: 96/Jan/23 DwightKr Created // //---------------------------------------------------------------------------- class CWQueryCache : public CDoubleList { public: CWQueryCache(); ~CWQueryCache(); CWQueryItem * CreateOrFindQuery( WCHAR const * wcsIDQFile, XPtr & variableSet, XPtr & outputFormat, CSecurityIdentity securityIdentity, BOOL & fAsynchronous ); void DeleteOldQueries(); void Release( CWQueryItem * pItem, BOOL fDecRunningQueries = TRUE ); #if (DBG == 1) BOOL Internal( CVariableSet & variableSet, COutputFormat & outputFormat, CVirtualString & string ); #endif // DBG == 1 void FlushCache(); void AddToCache( CWQueryItem * pItem ); BOOL AddToPendingRequestQueue( EXTENSION_CONTROL_BLOCK *pEcb ); void Shutdown(); void Wakeup() { _eventCacheWork.Set(); // wake up thread } void IncrementActiveRequests() { long x = InterlockedIncrement( & _cActiveRequests ); Win4Assert( 0 != x ); } void DecrementActiveRequests() { long x = InterlockedDecrement( & _cActiveRequests ); Win4Assert( 0xffffffff != x ); } void IncrementRejectedRequests() { InterlockedIncrement( & _cRequestsRejected ); *_pcRequestsRejected = _cRequestsRejected; } void UpdatePendingRequestCount(); // // State // ULONG Percent(ULONG num, ULONG den) { return (den == 0) ? 0: (ULONG)((((ULONGLONG) num * 100) + (den/2) ) / den); } ULONG Hits() { return Percent(*_pcCacheHits, *_pcCacheHitsAndMisses); } ULONG Misses() { return Percent(*_pcCacheMisses, *_pcCacheHitsAndMisses); } ULONG Running() { return *_pcRunningQueries; } ULONG Cached() { return *_pcCacheItems; } ULONG Rejected() { return *_pcRequestsRejected; } ULONG Total() { return *_pcTotalQueries; } ULONG QPM() { return *_pcQueriesPerMinute; } LONG ActiveRequestCount() { return _cActiveRequests; } unsigned PendingQueryCount() { return _pendingQueue.Count(); } private: ULONG GetNextSequenceNumber() { InterlockedIncrement( (LONG *) &_ulSequenceNumber ); return _ulSequenceNumber; } ULONG GetSequenceNumber() { return _ulSequenceNumber; } CWQueryItem * FindItem( CWQueryBookmark & bookmark, LONG lSkipCount, CSecurityIdentity securityIdentity ); CWQueryItem * FindItem( XPtr & variableSet, XPtr & outputFormat, WCHAR const * wcsIDQFile, CSecurityIdentity securityIdentity ); CWQueryItem * CreateNewQuery( WCHAR const * wcsIDQFile, XPtr & variableSet, XPtr & outputFormat, CSecurityIdentity securityIdentity, BOOL & fAsynchronous ); CWQueryItem * Pop() { return (CWQueryItem *) _Pop(); } void Push(CWQueryItem * pItem) { _Push( pItem ); } void LokMoveToFront( CWQueryItem * pItem ); static DWORD WINAPI WatchDogThread( void *self ); void ProcessCacheEvents(); BOOL CheckForCompletedQueries(); BOOL CheckForPendingRequests(); void IncrementRunningQueries() { long x = InterlockedIncrement( (LONG *)_pcRunningQueries ); // underflow check Win4Assert( 0 != x ); } void DecrementRunningQueries() { long x = InterlockedDecrement( (LONG *)_pcRunningQueries ); // underflow check Win4Assert( 0xffffffff != x ); } void Remove( CWQueryItem * pItem ); #if (DBG == 1) void Dump( CVirtualString & string, CVariableSet & variableSet, COutputFormat & outputFormat ); #endif // DBG == 1 ULONG _ulSignature; // Signature of start of privates ULONG _ulSequenceNumber; // Sequence # of each query issued ULONG * _pcCacheItems; // Number of items in cache ULONG * _pcCacheHits; // Number of cache hits ULONG * _pcCacheMisses; // Number of cache misses ULONG * _pcCacheHitsAndMisses; // Sum of hits and misses ULONG * _pcRunningQueries; // Number of running queries ULONG * _pcTotalQueries; // Number of new queries ULONG * _pcRequestsQueued; // current # of queued requests ULONG * _pcRequestsRejected; // total # of rejected requests ULONG * _pcQueriesPerMinute; // Queries / min. ~15 second average. LONG _cActiveRequests; // current # of active isapi requests LONG _cRequestsRejected; // total # of rejected isapi requests CMutexSem _mutex; // To serialize access to list CMutexSem _mutexShutdown; // To serialize access to shutdowns CEventSem _eventCacheWork; // Wakeup when time do work CThread _threadWatchDog; // Cache watch dog thread CIDQFileList _idqFileList; // Cache of parsed idq files CHTXFileList _htxFileList; // Cache of parsed htx files CDynArrayInPlace _pendingQueue; CNamedSharedMem _smPerf; // Shared memory for perf counters // // The "fake" perfcounters to shadow the real ones // CI_ISAPI_COUNTERS _smSpare; }; //+--------------------------------------------------------------------------- // // Class: CWQueryCacheForwardIter // // Purpose: Iterates forward over a CWQueryCache // // History: 96/Jan/23 DwightKr Created // //---------------------------------------------------------------------------- class CWQueryCacheForwardIter : public CForwardIter { public: CWQueryCacheForwardIter( CWQueryCache & list ) : CForwardIter(list) {} CWQueryItem * operator->() { return (CWQueryItem *) _pLinkCur; } CWQueryItem * Get() { return (CWQueryItem *) _pLinkCur; } }; void SetupDefaultCiVariables( CVariableSet & variableSet ); void SetupDefaultISAPIVariables( CVariableSet & variableSet ); //+--------------------------------------------------------------------------- // // Class: CWQueryCacheBackwardIter // // Purpose: Iterates backwards over a CWQueryCache // // History: 96/Jan/23 DwightKr Created // //---------------------------------------------------------------------------- class CWQueryCacheBackwardIter : public CBackwardIter { public: CWQueryCacheBackwardIter( CWQueryCache & list ) : CBackwardIter(list) {} CWQueryItem * operator->() { return (CWQueryItem *) _pLinkCur; } CWQueryItem * Get() { return (CWQueryItem *) _pLinkCur; } }; //+--------------------------------------------------------------------------- // // Class: CICommandItem // // Purpose: Info for an ICommand cache entry // // History: 97/Feb/23 dlee Created // //---------------------------------------------------------------------------- class CICommandItem { public: BOOL fInUse; XInterface xCommand; DWORD depth; XArray aMachine; XArray aCatalog; XArray aScope; }; //+--------------------------------------------------------------------------- // // Class: CICommandCache // // Purpose: A cache for ICommands, since they are expensive to create // // History: 97/Feb/23 dlee Created // //---------------------------------------------------------------------------- class CICommandCache { public: CICommandCache(); SCODE Make( ICommand ** ppCommand, DWORD depth, WCHAR const * pwcMachine, WCHAR const * pwcCatalog, WCHAR const * pwcScope ); void Release( ICommand * pCommand ); void Remove( ICommand * pCommand ); void Purge(); private: SCODE ParseAndMake( ICommand ** ppCommand, DWORD depth, WCHAR const * pwcMachine, WCHAR const * pwcCatalog, WCHAR const * pwcScope ); ULONG _ulSig; CMutexSem _mutex; XArray _aItems; XInterface xCmdCreator; }; //+--------------------------------------------------------------------------- // // Function: CopyString // // Purpose: Simple method to allocate and copy a string (strdup) // // History: 99-Feb-10 dlee Created // //---------------------------------------------------------------------------- inline WCHAR * CopyString( WCHAR const *pwc ) { unsigned c = wcslen( pwc ) + 1; WCHAR *pwcNew = new WCHAR[c]; RtlCopyMemory( pwcNew, pwc, c * sizeof WCHAR ); return pwcNew; } //CopyString //+--------------------------------------------------------------------------- // // Class: CFormatItem // // Purpose: Formatting information for a given locale // // History: 99-Feb-10 dlee Created // //---------------------------------------------------------------------------- class CFormatItem { public: CFormatItem( LCID lcid ); ~CFormatItem(); void Copy( NUMBERFMT & numberFormat, CURRENCYFMT & currencyFormat ) const; LCID GetLCID() const { return _lcid; } private: LCID _lcid; NUMBERFMT _numberFormat; CURRENCYFMT _currencyFormat; }; //+--------------------------------------------------------------------------- // // Class: CFormattingCache // // Purpose: Cache of formatting information. // // History: 99-Feb-10 dlee Created // //---------------------------------------------------------------------------- class CFormattingCache { public: CFormattingCache() {} void GetFormattingInfo( LCID lcid, NUMBERFMT & numberFormat, CURRENCYFMT & currencyFormat ); void Purge(); private: CMutexSem _mutex; CCountedDynArray _aItems; }; class CTheGlobalIDQVariables; extern CTheGlobalIDQVariables * pTheGlobalIDQVariables; class CIDQTheFirst { public: CIDQTheFirst( CTheGlobalIDQVariables *p ) { pTheGlobalIDQVariables = p; } }; class CTheGlobalIDQVariables { public: CTheGlobalIDQVariables() : #pragma warning(disable : 4355) // 'this' in a constructor _first(this), #pragma warning(default : 4355) // 'this' in a constructor _fTheWebActiveXSearchShutdown(FALSE) { } CIDQTheFirst _first; BOOL _fTheWebActiveXSearchShutdown; CIdqRegParams _TheIDQRegParams; CICommandCache _TheICommandCache; CWebResourceArbiter _TheWebResourceArbiter; CWebPendingQueue _TheWebPendingRequestQueue; CWQueryCache _TheWebQueryCache; CFormattingCache _TheFormattingCache; }; #define TheGlobalIDQVariables (*pTheGlobalIDQVariables) #define TheIDQRegParams TheGlobalIDQVariables._TheIDQRegParams #define TheWebQueryCache TheGlobalIDQVariables._TheWebQueryCache #define TheWebPendingRequestQueue TheGlobalIDQVariables._TheWebPendingRequestQueue #define TheWebResourceArbiter TheGlobalIDQVariables._TheWebResourceArbiter #define fTheActiveXSearchShutdown TheGlobalIDQVariables._fTheWebActiveXSearchShutdown #define TheICommandCache TheGlobalIDQVariables._TheICommandCache #define TheFormattingCache TheGlobalIDQVariables._TheFormattingCache