|
|
//+------------------------------------------------------------------
//
// Copyright (C) 1991-1997 Microsoft Corporation.
//
// File: idxentry.cxx
//
// Contents: Document filter interface
//
// Classes: CIndexNotificationEntry
//
// History: 24-Feb-97 SitaramR Created
//
// Notes: The implementation uses the regular memory allocator,
// and it makes a copy of every text string and property
// that is added. A better approach may be to define a
// custom memory allocator that allocates portions as
// needed from say a 4K block of memory.
//
//-------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <cifrmcom.hxx>
#include "idxentry.hxx"
#include "cimanger.hxx"
//+---------------------------------------------------------------------------
//
// Member: CChunkEntry::CChunkEntry
//
// Synopsis: Constructor
//
// Arguments: [pStatChunk] -- Pointer to stat chunk
// [pwszText] -- Text
//
// History: 24-Feb-97 SitaramR Created
//
//----------------------------------------------------------------------------
CChunkEntry::CChunkEntry( STAT_CHUNK const * pStatChunk, WCHAR const *pwszText ) : _pChunkEntryNext( 0 ) { _statChunk = *pStatChunk;
XPtrST<WCHAR> xPropString; if ( _statChunk.attribute.psProperty.ulKind == PRSPEC_LPWSTR ) { //
// Make own copy of property string
//
ULONG cwcLen = wcslen( pStatChunk->attribute.psProperty.lpwstr ) + 1; _statChunk.attribute.psProperty.lpwstr = new WCHAR[cwcLen]; RtlCopyMemory( _statChunk.attribute.psProperty.lpwstr, pStatChunk->attribute.psProperty.lpwstr, cwcLen * sizeof( WCHAR ) );
xPropString.Set( _statChunk.attribute.psProperty.lpwstr ); }
ULONG cwcLen = wcslen( pwszText ) + 1; _pwszText = new WCHAR[cwcLen]; RtlCopyMemory( _pwszText, pwszText, cwcLen * sizeof(WCHAR) );
xPropString.Acquire(); // Pass ownership to CChunkEntry
}
//+---------------------------------------------------------------------------
//
// Member: CChunkEntry::CChunkEntry
//
// Synopsis: Constructor
//
// Arguments: [pStatChunk] -- Pointer to stat chunk
// [pPropVar] -- Property
//
// History: 24-Feb-97 SitaramR Created
//
//----------------------------------------------------------------------------
CChunkEntry::CChunkEntry( STAT_CHUNK const * pStatChunk, PROPVARIANT const * pPropVar ) : _pChunkEntryNext( 0 ) { _statChunk = *pStatChunk;
XPtrST<WCHAR> xPropString; if ( _statChunk.attribute.psProperty.ulKind == PRSPEC_LPWSTR ) { //
// Make own copy of property string
//
ULONG cwcLen = wcslen( pStatChunk->attribute.psProperty.lpwstr ) + 1; _statChunk.attribute.psProperty.lpwstr = new WCHAR[cwcLen]; RtlCopyMemory( _statChunk.attribute.psProperty.lpwstr, pStatChunk->attribute.psProperty.lpwstr, cwcLen * sizeof( WCHAR ) );
xPropString.Set( _statChunk.attribute.psProperty.lpwstr ); }
_pStgVariant = new CStorageVariant( *(PROPVARIANT *)pPropVar ); if ( _pStgVariant == 0 ) THROW( CException( E_OUTOFMEMORY ) );
xPropString.Acquire(); // Pass ownership to CChunkEntry
}
//+---------------------------------------------------------------------------
//
// Member: CChunkEntry::~CChunkEntry
//
// Synopsis: Destructor
//
// History: 24-Feb-97 SitaramR Created
//
//----------------------------------------------------------------------------
CChunkEntry::~CChunkEntry() { if ( _statChunk.attribute.psProperty.ulKind == PRSPEC_LPWSTR ) delete _statChunk.attribute.psProperty.lpwstr;
if ( _statChunk.flags == CHUNK_TEXT ) delete _pwszText; else delete _pStgVariant; }
//+---------------------------------------------------------------------------
//
// Member: CIndexNotificationEntry::CIndexNotificationEntry
//
// Synopsis: Constructor
//
// History: 24-Feb-97 SitaramR Created
//
//----------------------------------------------------------------------------
CIndexNotificationEntry::CIndexNotificationEntry( WORKID wid, CI_UPDATE_TYPE eUpdateType, XInterface<CIndexNotificationTable> & xNotifTable, XInterface<ICiCIndexNotificationStatus> & xNotifStatus, CCiManager * pCiManager, USN usn ) : _xNotifTable( xNotifTable.Acquire() ), _xNotifStatus( xNotifStatus.Acquire() ), _pCiManager( pCiManager ), _wid( wid ), _eUpdateType( eUpdateType ), _fAddCompleted( FALSE ), _fShutdown( FALSE ), _fFilterDataPurged( FALSE ), _usn( usn ), _pChunkEntryHead( 0 ), _pChunkEntryTail( 0 ), _pChunkEntryIter( 0 ), _cRefs( 1 ) { }
//+---------------------------------------------------------------------------
//
// Member: CIndexNotificationEntry::~CIndexNotificationEntry
//
// Synopsis: Destructor
//
// History: 24-Feb-97 SitaramR Created
//
//----------------------------------------------------------------------------
CIndexNotificationEntry::~CIndexNotificationEntry() { PurgeFilterData(); }
//+-------------------------------------------------------------------------
//
// Method: CIndexNotificationEntry::AddRef
//
// Synopsis: Increments refcount
//
// History: 24-Feb-1997 SitaramR Created
//
//--------------------------------------------------------------------------
ULONG STDMETHODCALLTYPE CIndexNotificationEntry::AddRef() { return InterlockedIncrement( (long *) &_cRefs ); }
//+-------------------------------------------------------------------------
//
// Method: CIndexNotificationEntry::Release
//
// Synopsis: Decrement refcount. Delete if necessary.
//
// History: 24-Feb-1997 SitaramR Created
//
//--------------------------------------------------------------------------
ULONG STDMETHODCALLTYPE CIndexNotificationEntry::Release() { Win4Assert( _cRefs > 0 );
ULONG uTmp = InterlockedDecrement( (long *) &_cRefs );
if ( 0 == uTmp ) delete this;
return uTmp; }
//+-------------------------------------------------------------------------
//
// Method: CIndexNotificationEntry::QueryInterface
//
// Synopsis: Rebind to other interface
//
// Arguments: [riid] -- IID of new interface
// [ppvObject] -- New interface * returned here
//
// Returns: S_OK if bind succeeded, E_NOINTERFACE if bind failed
//
// History: 24-Feb-1997 SitaramR Created
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE CIndexNotificationEntry::QueryInterface( REFIID riid, void ** ppvObject) { Win4Assert( 0 != ppvObject );
if ( riid == IID_ICiIndexNotificationEntry ) *ppvObject = (void *)(ICiIndexNotificationEntry *) this; else if ( riid == IID_IUnknown ) *ppvObject = (void *)(IUnknown *) this; else { *ppvObject = 0; return E_NOINTERFACE; }
AddRef(); return S_OK; }
//+-------------------------------------------------------------------------
//
// Method: CIndexNotificationEntry::AddText
//
// Synopsis: Adds a text chunk
//
// Arguments: [pStatChunk] -- Pointer to stat chunk
// [pwszText] -- Text
//
// History: 24-Feb-1997 SitaramR Created
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE CIndexNotificationEntry::AddText( STAT_CHUNK const * pStatChunk, WCHAR const * pwszText ) { if ( _fShutdown ) return CI_E_SHUTDOWN;
if ( _fAddCompleted ) { Win4Assert( !"Adding text after AddCompleted was signalled" );
return E_FAIL; }
Win4Assert( pStatChunk->flags == CHUNK_TEXT );
SCODE sc = S_OK;
TRY { CChunkEntry *pEntry = new CChunkEntry( pStatChunk, pwszText ); if ( _pChunkEntryTail ) { _pChunkEntryTail->SetNextChunkEntry( pEntry ); // does not fail
_pChunkEntryTail = pEntry; }
else { _pChunkEntryTail = pEntry; _pChunkEntryHead = pEntry; } } CATCH( CException, e ) { sc = e.GetErrorCode();
ciDebugOut(( DEB_ERROR, "CIndexNotificationEntry::AddText - Exception caught 0x%x\n", sc )); } END_CATCH;
return sc; }
//+-------------------------------------------------------------------------
//
// Method: CIndexNotificationEntry::AddProperty
//
// Synopsis: Adds a property chunk
//
// Arguments: [pStatChunk] -- Pointer to stat chunk
// [pPropVar] -- Property
//
// History: 24-Feb-1997 SitaramR Created
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE CIndexNotificationEntry::AddProperty( STAT_CHUNK const * pStatChunk, PROPVARIANT const *pPropVar ) { if ( _fShutdown ) return CI_E_SHUTDOWN;
if ( _fAddCompleted ) { Win4Assert( !"Adding property after AddCompleted was signalled" );
return E_FAIL; }
Win4Assert( pStatChunk->flags == CHUNK_VALUE );
SCODE sc = S_OK;
TRY { CChunkEntry *pEntry = new CChunkEntry( pStatChunk, pPropVar ); if ( _pChunkEntryTail ) { _pChunkEntryTail->SetNextChunkEntry( pEntry ); // does not fail
_pChunkEntryTail = pEntry; } else { _pChunkEntryTail = pEntry; _pChunkEntryHead = pEntry; } } CATCH( CException, e ) { sc = e.GetErrorCode();
ciDebugOut(( DEB_ERROR, "CIndexNotificationEntry::AddProperty - Exception caught 0x%x\n", sc )); } END_CATCH;
return sc; }
//+-------------------------------------------------------------------------
//
// Method: CIndexNotificationEntry::AddCompleted
//
// Synopsis: Signifies end of chunks. At this time the notification is
// propagated to CCiManager.
//
// Arguments: [fAbort] -- If true, then the notification should not be
// propagted to ICiManager. Also, all resources
// need to be released
//
// History: 24-Feb-1997 SitaramR Created
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE CIndexNotificationEntry::AddCompleted( ULONG fAbort ) { if ( _fAddCompleted ) { Win4Assert( !"AddCompleted being called for the second time" );
return E_FAIL; }
SCODE sc = S_OK;
TRY { CIndexNotificationEntry *pNotifEntry; _fAddCompleted = TRUE;
if ( fAbort || _fShutdown ) { SCODE scode = _xNotifStatus->Abort();
//
// We don't have retry logic on failures
//
Win4Assert( SUCCEEDED( scode ) );
//
// Free entry from hash table, which should be ourself
//
XInterface<CIndexNotificationEntry> xIndexNotifEntry; _xNotifTable->Remove( _wid, xIndexNotifEntry );
Win4Assert( this == xIndexNotifEntry.GetPointer() );
//
// xIndexNotifEntry is released when it goes out of scope
//
} else { CDocumentUpdateInfo info( _wid, CI_VOLID_USN_NOT_ENABLED, _usn, FALSE ); sc = _pCiManager->UpdDocumentNoThrow( &info );
if ( FAILED( sc ) ) { SCODE scode = _xNotifStatus->Abort();
//
// We don't have retry logic on failures
//
Win4Assert( SUCCEEDED( scode ) );
//
// Free entry from hash table, which should be ourself
//
XInterface<CIndexNotificationEntry> xIndexNotifEntry; _xNotifTable->Remove( _wid, xIndexNotifEntry );
Win4Assert( this == xIndexNotifEntry.GetPointer() );
//
// xIndexNotifEntry is released when it goes out of scope
//
} } } CATCH( CException, e ) { sc = e.GetErrorCode();
ciDebugOut(( DEB_ERROR, "CIndexNotificationEntry::AddCompleted - Exception caught 0x%x\n", sc )); //
// Not clear why AddCompleted can ever fail
//
Win4Assert( !"AddCompleted failed" ); } END_CATCH;
return sc; }
//+-------------------------------------------------------------------------
//
// Method: CIndexNotificationEntry::GetFirstChunk
//
// Synopsis: Returns first entry in list of chunks
//
// History: 24-Feb-1997 SitaramR Created
//
//--------------------------------------------------------------------------
CChunkEntry *CIndexNotificationEntry::GetFirstChunk() { if ( _fFilterDataPurged ) { Win4Assert( !"Re-filtering is not allowed in push filtering" );
return 0; } _pChunkEntryIter = _pChunkEntryHead; return _pChunkEntryIter; }
//+-------------------------------------------------------------------------
//
// Method: CIndexNotificationEntry::GetNextChunk
//
// Synopsis: Returns next entry in list of chunks. The state of iterator
// is maintained in _pChunkEntryIter, which can be reset by
// GetFirstChunk.
//
// History: 24-Feb-1997 SitaramR Created
//
//--------------------------------------------------------------------------
CChunkEntry *CIndexNotificationEntry::GetNextChunk() { if ( _fFilterDataPurged ) { Win4Assert( !"Re-filtering is not allowed in push filtering" );
return 0; } if ( _pChunkEntryIter == 0 ) return 0; else { _pChunkEntryIter = _pChunkEntryIter->GetNextChunkEntry(); return _pChunkEntryIter; } }
//+-------------------------------------------------------------------------
//
// Method: CIndexNotificationEntry::PurgeFilterData
//
// Synopsis: Deletes filter data, because wids are filtered only once
// in push filtering.
//
// History: 17-Jun-1997 SitaramR Created
//
//--------------------------------------------------------------------------
void CIndexNotificationEntry::PurgeFilterData() { _fFilterDataPurged = TRUE; //
// Clean up all chunks
//
if ( _pChunkEntryHead != 0 ) { CChunkEntry *pEntryPrev = _pChunkEntryHead; CChunkEntry *pEntryNext = pEntryPrev->GetNextChunkEntry();
while ( pEntryNext != 0 ) { delete pEntryPrev; pEntryPrev = pEntryNext; pEntryNext = pEntryNext->GetNextChunkEntry(); }
delete pEntryPrev;
_pChunkEntryHead = 0; } }
|