Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1329 lines
40 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2002.
  5. //
  6. // File: cimanger.cxx
  7. //
  8. // Contents: The Content Index manager object implementing the
  9. // ICiManager interface.
  10. //
  11. // History: 12-03-96 srikants Created
  12. //
  13. //----------------------------------------------------------------------------
  14. #include <pch.cxx>
  15. #pragma hdrstop
  16. #include <cci.hxx>
  17. #include <prcstob.hxx>
  18. #include <glbconst.hxx>
  19. #include <idxtab.hxx>
  20. #include <enumstr.hxx>
  21. #include "cimanger.hxx"
  22. #include "dmnslave.hxx"
  23. CCiManager::CCiManager( ICiCDocStore * pICiCDocStore )
  24. :_sigCiManger(sigCiManger),
  25. _refCount(1),
  26. _state(STARTING),
  27. _reason(INVALID_REASON),
  28. _pcci(0),
  29. _startupFlags(0),
  30. _fInProc(FALSE),
  31. _pFilterDaemon(0),
  32. _pPidLookupTable(0),
  33. _fNullContentIndex( FALSE )
  34. {
  35. Win4Assert( pICiCDocStore );
  36. pICiCDocStore->AddRef();
  37. _xDocStore.Set( pICiCDocStore );
  38. ICiCAdviseStatus *pAdviseStatus = 0;
  39. SCODE sc = _xDocStore->QueryInterface( IID_ICiCAdviseStatus,
  40. (void **) &pAdviseStatus);
  41. if ( S_OK != sc )
  42. {
  43. Win4Assert( 0 != pAdviseStatus );
  44. THROW(CException(sc) );
  45. }
  46. _xAdviseStatus.Set(pAdviseStatus);
  47. ICiCLangRes *pICiCLangRes;
  48. sc = pICiCDocStore->QueryInterface(IID_ICiCLangRes, (void **) &pICiCLangRes);
  49. if ( FAILED(sc) )
  50. {
  51. Win4Assert( !"QI on ICiCLangRes failed" );
  52. THROW (CException(sc));
  53. }
  54. XInterface<ICiCLangRes> xCiCLangRes(pICiCLangRes);
  55. _xLangList.Set( new CLangList(pICiCLangRes) );
  56. CCiAdminParams * pAdminParams = new CCiAdminParams( _xLangList.GetPointer() );
  57. _xAdminParams.Set( pAdminParams );
  58. CCiFrameworkParams * pFrameParams = new CCiFrameworkParams( pAdminParams );
  59. _xFrameParams.Set( pFrameParams );
  60. }
  61. CCiManager::~CCiManager()
  62. {
  63. Win4Assert( 0 == _refCount );
  64. delete _pFilterDaemon;
  65. delete _pcci;
  66. }
  67. //+---------------------------------------------------------------------------
  68. //
  69. // Member: CCiManager::QueryInterface
  70. //
  71. // Synopsis: Returns interfaces to IID_IUknown, IID_ICiManager,
  72. // IID_ICiStartup, IID_ICiAdmin, IID_ICiFrameworkQuery,
  73. // IID_ISimpleCommandCreator
  74. //
  75. // History: 11-27-96 srikants Created
  76. // 2-14-97 mohamedn ICiAdmin and ICiFrameworkQuery
  77. // 04-23-97 KrishnaN Exposed IID_ISimpleCommandCreator
  78. // 04-23-97 KrishnaN Replaced RtlEqualMemory with ==
  79. //
  80. //----------------------------------------------------------------------------
  81. STDMETHODIMP CCiManager::QueryInterface(
  82. REFIID riid,
  83. void **ppvObject)
  84. {
  85. Win4Assert( 0 != ppvObject );
  86. if ( IID_ISimpleCommandCreator == riid )
  87. *ppvObject = (void *)((ISimpleCommandCreator *)this);
  88. else if ( IID_ICiManager == riid )
  89. *ppvObject = (void *)((ICiManager *)this);
  90. else if ( IID_ICiStartup == riid )
  91. *ppvObject = (void *)((ICiStartup *)this);
  92. else if ( IID_ICiAdmin == riid )
  93. *ppvObject = (void *)((ICiAdmin *)this);
  94. else if ( IID_ICiFrameworkQuery == riid )
  95. *ppvObject = (void *)((ICiFrameworkQuery *)this);
  96. else if ( IID_ICiPersistIncrFile == riid )
  97. *ppvObject = (void *)((ICiPersistIncrFile *)this);
  98. else if ( (IID_ICiIndexNotification == riid )
  99. && !_xIndexNotifTable.IsNull() )
  100. {
  101. return _xIndexNotifTable->QueryInterface( riid, ppvObject );
  102. }
  103. else if ( IID_IUnknown == riid )
  104. *ppvObject = (void *)((IUnknown *) (ICiManager *) this);
  105. else
  106. {
  107. *ppvObject = 0;
  108. return E_NOINTERFACE;
  109. }
  110. AddRef();
  111. return S_OK;
  112. } //QueryInterface
  113. //+---------------------------------------------------------------------------
  114. //
  115. // Member: CCiManager::AddRef
  116. //
  117. // History: 11-22-96 srikants Created
  118. //
  119. //----------------------------------------------------------------------------
  120. STDMETHODIMP_(ULONG) CCiManager::AddRef()
  121. {
  122. return InterlockedIncrement(&_refCount);
  123. } //AddRef
  124. //+---------------------------------------------------------------------------
  125. //
  126. // Member: CCiManager::Release
  127. //
  128. // History: 11-22-96 srikants Created
  129. //
  130. //----------------------------------------------------------------------------
  131. STDMETHODIMP_(ULONG) CCiManager::Release()
  132. {
  133. Win4Assert( _refCount > 0 );
  134. LONG refCount = InterlockedDecrement(&_refCount);
  135. if ( refCount <= 0 )
  136. delete this;
  137. return (ULONG) refCount;
  138. } //Release
  139. //+---------------------------------------------------------------------------
  140. //
  141. // Member: CCiManager::GetStatus
  142. //
  143. // Synopsis: Retrieves the Content Index status
  144. //
  145. // Arguments: [pCiState] -
  146. //
  147. // History: 1-08-97 srikants Created
  148. //
  149. //----------------------------------------------------------------------------
  150. STDMETHODIMP CCiManager::GetStatus(CIF_STATE *pCiState)
  151. {
  152. Win4Assert( 0 != pCiState );
  153. SCODE sc = S_OK;
  154. if ( 0 != _pcci )
  155. _pcci->CiState( *pCiState );
  156. else
  157. sc = CI_E_NOT_INITIALIZED;
  158. return sc;
  159. }
  160. //+---------------------------------------------------------------------------
  161. //
  162. // Member: CCiManager::Empty
  163. //
  164. // Synopsis: Empties all the contents of the Content Index.
  165. //
  166. // History: 1-08-97 srikants Created
  167. //
  168. //----------------------------------------------------------------------------
  169. STDMETHODIMP CCiManager::Empty()
  170. {
  171. SCODE sc = S_OK;
  172. if ( 0 != _pcci )
  173. _pcci->Empty();
  174. else
  175. sc = CI_E_NOT_INITIALIZED;
  176. return sc;
  177. }
  178. //+---------------------------------------------------------------------------
  179. //
  180. // Member: CCiManager::Shutdown
  181. //
  182. // Synopsis: Shuts down Content Index. Cannot initiate any more queries after
  183. // this.
  184. //
  185. // Returns: SCODE of the operation.
  186. //
  187. // History: 12-09-96 srikants Created
  188. //
  189. //----------------------------------------------------------------------------
  190. STDMETHODIMP CCiManager::Shutdown()
  191. {
  192. SCODE sc = S_OK;
  193. // =======================================
  194. {
  195. CLock lock(_mutex);
  196. if ( IsShutdown() )
  197. return CI_E_SHUTDOWN;
  198. _state = SHUTDOWN;
  199. }
  200. // =======================================
  201. _saveTracker.SetAbort();
  202. if ( _pFilterDaemon )
  203. _pFilterDaemon->InitiateShutdown();
  204. if ( _pcci )
  205. _pcci->Dismount();
  206. //
  207. // Wait for the death of the filter daemon thread.
  208. //
  209. if ( _pFilterDaemon )
  210. _pFilterDaemon->WaitForDeath();
  211. _saveTracker.WaitForCompletion();
  212. //
  213. // Shutdown buffered notifications in push filtering,
  214. // _after_ the filter thread has terminated.
  215. //
  216. if ( !_xIndexNotifTable.IsNull() )
  217. _xIndexNotifTable->Shutdown();
  218. _xPropMapper.Free();
  219. _xDocStore.Free();
  220. return S_OK;
  221. }
  222. //+---------------------------------------------------------------------------
  223. //
  224. // Member: CCiManager::UpdateDocument
  225. //
  226. // Synopsis: Schedules a document for update and filtering.
  227. //
  228. // Arguments: [pInfo] - Information about the document to be updated.
  229. //
  230. // History: 12-09-96 srikants Created
  231. //
  232. //----------------------------------------------------------------------------
  233. STDMETHODIMP CCiManager::UpdateDocument(
  234. const CI_DOCUMENT_UPDATE_INFO * pInfo )
  235. {
  236. if ( _xIndexNotifTable.IsNull() )
  237. return UpdDocumentNoThrow( pInfo );
  238. else
  239. {
  240. // Win4Assert( !"UpdateDocument is not available in push filtering" );
  241. ciDebugOut ((DEB_ERROR,
  242. "UpdateDocument is not available in push filtering, wid = 0x%x\n",
  243. pInfo->workId ));
  244. return E_FAIL;
  245. }
  246. }
  247. //+---------------------------------------------------------------------------
  248. //
  249. // Member: CCiManager::StartupNullContentIndex
  250. //
  251. // Synopsis: Starts up the NULL content index.
  252. //
  253. // Arguments: [pwszCiDirectory] - Starting directory for storing CI data.
  254. // [pStartupInfo] - Startup information.
  255. // [pIProgressNotify] - Progress notification i/f
  256. // [pfAbort] - Ptr to flag controlling abort.
  257. //
  258. // History: Jul-09-97 KrishnaN Created
  259. //
  260. // Notes: The thread calling this MUST be in the SYSTEM/ADMINISTRATIVE
  261. // context, ie, have the highest privilege needed for Content Index.
  262. //
  263. //----------------------------------------------------------------------------
  264. STDMETHODIMP CCiManager::StartupNullContentIndex(
  265. CI_STARTUP_INFO * pStartupInfo,
  266. IProgressNotify *pIProgressNotify,
  267. BOOL * pfAbort )
  268. {
  269. // Anything but null for the second param...
  270. return StartupContentIndex(TRUE, CINULLCATALOG, pStartupInfo, pIProgressNotify, pfAbort);
  271. }
  272. //+---------------------------------------------------------------------------
  273. //
  274. // Member: CCiManager::StartupContentIndex
  275. //
  276. // Synopsis: Starts up the content index using the startup parameters
  277. // provided.
  278. //
  279. // Arguments: [pwszCiDirectory] - Starting directory for storing CI data.
  280. // [pStartupInfo] - Startup information.
  281. // [pIProgressNotify] - Progress notification i/f
  282. // [pfAbort] - Ptr to flag controlling abort.
  283. //
  284. // History: 12-09-96 srikants Created
  285. //
  286. // Notes: The thread calling this MUST be in the SYSTEM/ADMINISTRATIVE
  287. // context, ie, have the highest privilege needed for Content Index.
  288. //
  289. //----------------------------------------------------------------------------
  290. STDMETHODIMP CCiManager::StartupContentIndex(
  291. const WCHAR * pwszCiDirectory,
  292. CI_STARTUP_INFO * pStartupInfo,
  293. IProgressNotify *pIProgressNotify,
  294. BOOL * pfAbort )
  295. {
  296. return StartupContentIndex(FALSE, pwszCiDirectory, pStartupInfo, pIProgressNotify, pfAbort);
  297. }
  298. //+---------------------------------------------------------------------------
  299. //
  300. // Member: CCiManager::StartupContentIndex
  301. //
  302. // Synopsis: Starts up the content index using the startup parameters
  303. // provided.
  304. //
  305. // Arguments: [fNullContentIndex] - Null content index?
  306. // [pwszCiDirectory] - Starting directory for storing CI data.
  307. // [pStartupInfo] - Startup information.
  308. // [pIProgressNotify] - Progress notification i/f
  309. // [pfAbort] - Ptr to flag controlling abort.
  310. //
  311. // History: 12-09-96 srikants Created
  312. // 02-17-98 kitmanh Passed fReadOnly into CiStorage
  313. // constructor
  314. // 01-Nov-98 KLam Passed DiskSpaceToLeave to CiStorage
  315. //
  316. // Notes: The thread calling this MUST be in the SYSTEM/ADMINISTRATIVE
  317. // context, ie, have the highest privilege needed for Content Index.
  318. //
  319. //----------------------------------------------------------------------------
  320. SCODE CCiManager::StartupContentIndex(
  321. BOOL fNullContentIndex,
  322. const WCHAR * pwszCiDirectory,
  323. CI_STARTUP_INFO * pStartupInfo,
  324. IProgressNotify *pIProgressNotify,
  325. BOOL * pfAbort )
  326. {
  327. Win4Assert( !CImpersonateSystem::IsImpersonated() );
  328. Win4Assert( 0 != pwszCiDirectory && 0 != pStartupInfo );
  329. _fNullContentIndex = fNullContentIndex;
  330. CLock lock(_mutex);
  331. if ( STARTING != _state )
  332. {
  333. return CI_E_INVALID_STATE;
  334. }
  335. _startupFlags = pStartupInfo->startupFlags;
  336. BOOL fPushFiltering = FALSE;
  337. if (!fNullContentIndex)
  338. {
  339. _fInProc = pStartupInfo->startupFlags & CI_CONFIG_INPROCESS_FILTERING;
  340. fPushFiltering = pStartupInfo->startupFlags & CI_CONFIG_PUSH_FILTERING;
  341. if ( fPushFiltering && !_fInProc )
  342. {
  343. Win4Assert( !"Simple filtering is supported only with in process filtering" );
  344. return E_INVALIDARG;
  345. }
  346. }
  347. SCODE sc = S_OK;
  348. TRY
  349. {
  350. if ( !fNullContentIndex && fPushFiltering )
  351. {
  352. XInterface<ICiCDocStore> xDocStore( _xDocStore.GetPointer() );
  353. xDocStore->AddRef();
  354. _xIndexNotifTable.Set( new CIndexNotificationTable( this,
  355. xDocStore ) );
  356. }
  357. BOOL fEnableFiltering =
  358. pStartupInfo->startupFlags & CI_CONFIG_ENABLE_INDEXING;
  359. // If this is a null content index, filtering should be disabled.
  360. Win4Assert( (fNullContentIndex && !fEnableFiltering) || !fNullContentIndex);
  361. if ( 0 == _pcci )
  362. {
  363. CLowcaseBuf lcaseDir( pwszCiDirectory );
  364. //
  365. // Make a copy to be acquired by CCiManager.
  366. //
  367. XArray<WCHAR> xDirCopy( lcaseDir.Length()+1 );
  368. if (!fNullContentIndex)
  369. {
  370. RtlCopyMemory( xDirCopy.GetPointer(), lcaseDir.Get(), xDirCopy.SizeOf() );
  371. //
  372. // Create a PStorage object for CI framework data.
  373. //
  374. if ( 0 == _xStorage.GetPointer() )
  375. {
  376. BOOL fReadOnly = (pStartupInfo->startupFlags & CI_CONFIG_READONLY) ? TRUE : FALSE;
  377. CiStorage * pStorage = new CiStorage( lcaseDir.Get(),
  378. _xAdviseStatus.GetReference(),
  379. _xFrameParams->GetMinDiskSpaceToLeave(),
  380. CURRENT_VERSION_STAMP,
  381. fReadOnly );
  382. _xStorage.Set( pStorage );
  383. }
  384. }
  385. //
  386. // Try to obtain a property mapper from the docstore. If successful,
  387. // we don't have to create one. O/W, we create a property mapper.
  388. //
  389. XInterface<IPropertyMapper> xPropMapper;
  390. IPropertyMapper * pPropMapper = 0;
  391. if ( pStartupInfo->startupFlags & CI_CONFIG_PROVIDE_PROPERTY_MAPPER )
  392. {
  393. xPropMapper.Set( _LokCreatePropertyMapper() );
  394. }
  395. else
  396. {
  397. SCODE scPropMapper = _xDocStore->GetPropertyMapper( &pPropMapper );
  398. if ( !SUCCEEDED(scPropMapper) )
  399. {
  400. ciDebugOut(( DEB_ERROR,
  401. "DocStore Is not providing property mapper. Error 0x%X\n",
  402. scPropMapper ));
  403. THROW( CException( E_INVALIDARG ) );
  404. }
  405. xPropMapper.Set( pPropMapper );
  406. }
  407. //
  408. // Update the worker queue registry settings.
  409. //
  410. _UpdateQueryWorkerQueueParams();
  411. //
  412. // Save the CLSID of the client manager in daemon process.
  413. //
  414. _clsidDmnClientMgr = pStartupInfo->clsidDaemonClientMgr;
  415. if (!fNullContentIndex)
  416. {
  417. if ( !_xIndexNotifTable.IsNull() )
  418. _xIndexNotifTable->AddRef();
  419. XInterface<CIndexNotificationTable> xNotifTable( _xIndexNotifTable.GetPointer() );
  420. _pcci = new CCI( _xStorage.GetReference(),
  421. _xFrameParams.GetReference(),
  422. _xDocStore.GetPointer(),
  423. *pStartupInfo,
  424. xPropMapper.GetPointer(),
  425. xNotifTable );
  426. _xCiDir.Set( xDirCopy.Count(), xDirCopy.Get() );
  427. xDirCopy.Acquire();
  428. }
  429. _xPropMapper.Set( xPropMapper.Acquire() );
  430. //
  431. // Move to the next state depending upon the startup options.
  432. //
  433. if ( fEnableFiltering )
  434. {
  435. //
  436. // Check the disk free space situation.
  437. //
  438. _state = READY_TO_FILTER;
  439. }
  440. else
  441. {
  442. _state = FILTERING_DISABLED;
  443. _reason = DISABLED_ON_STARTUP;
  444. }
  445. }
  446. else
  447. {
  448. sc = CI_E_ALREADY_INITIALIZED;
  449. }
  450. }
  451. CATCH( CException, e )
  452. {
  453. sc = e.GetErrorCode();
  454. }
  455. END_CATCH
  456. return sc;
  457. }
  458. //+---------------------------------------------------------------------------
  459. //
  460. // Member: CCiManager::_LokGetStartFilteringError
  461. //
  462. // Synopsis: Determines the error code to be returned in the
  463. // StartFiltering() method based upon the current state.
  464. //
  465. // Returns:
  466. //
  467. // History: 12-10-96 srikants Created
  468. //
  469. //----------------------------------------------------------------------------
  470. SCODE CCiManager::_LokGetStartFilteringError() const
  471. {
  472. Win4Assert( READY_TO_FILTER != _state );
  473. if ( FILTERING_DISABLED == _state )
  474. {
  475. Win4Assert( INVALID_REASON != _reason );
  476. if ( DISABLED_ON_STARTUP == _state )
  477. {
  478. return CI_E_FILTERING_DISABLED;
  479. }
  480. else if ( DISABLED_FOR_DISK_FULL == _reason )
  481. {
  482. return CI_E_DISK_FULL;
  483. }
  484. else
  485. {
  486. return CI_E_INVALID_STATE;
  487. }
  488. }
  489. else if ( FILTERING_ENABLED == _state )
  490. {
  491. return S_OK; // already enabled.
  492. }
  493. else
  494. {
  495. return CI_E_INVALID_STATE;
  496. }
  497. }
  498. //+---------------------------------------------------------------------------
  499. //
  500. // Member: CCiManager::StartFiltering
  501. //
  502. // Synopsis: Start the filtering process
  503. //
  504. // Arguments: [cbData] - Count of bytes in startup data
  505. // [pbData] - Pointer to startup data
  506. //
  507. // Returns: CI_E_DISK_FULL if the disk is full and so filtering cannot be
  508. // started.
  509. //
  510. // CI_E_FILTERING_DISABLED if filtering was disabled in the startup
  511. // options.
  512. //
  513. // CI_E_INVALID_STATE if this is not a valid call in this state.
  514. // Usually signifies that shutdown is in progress.
  515. //
  516. // History: 12-09-96 srikants Created
  517. //
  518. //----------------------------------------------------------------------------
  519. STDMETHODIMP CCiManager::StartFiltering(
  520. ULONG cbData,
  521. BYTE const * pbData )
  522. {
  523. SCODE sc = S_OK;
  524. // ==============================================================
  525. {
  526. CLock lock(_mutex);
  527. if ( READY_TO_FILTER != _state )
  528. {
  529. return _LokGetStartFilteringError();
  530. }
  531. TRY
  532. {
  533. if ( 0 == _pFilterDaemon )
  534. {
  535. CSharedNameGen nameGen( _xCiDir.Get() );
  536. _pFilterDaemon = new CDaemonSlave( *this,
  537. _pcci,
  538. _xCiDir.Get(),
  539. nameGen,
  540. _clsidDmnClientMgr );
  541. }
  542. _pFilterDaemon->StartFiltering( pbData, cbData);
  543. _state = FILTERING_ENABLED;
  544. }
  545. CATCH( CException, e )
  546. {
  547. sc = e.GetErrorCode();
  548. }
  549. END_CATCH
  550. }
  551. // ==============================================================
  552. return sc;
  553. }
  554. //+---------------------------------------------------------------------------
  555. //
  556. // Member: CCiManager::FlushUpdates
  557. //
  558. // Synopsis: Flushes all update notifications to disk
  559. //
  560. // Returns: S_OK if successful; error code otherwise.
  561. //
  562. // History: 27-Jun-97 SitaramR Created
  563. //
  564. //----------------------------------------------------------------------------
  565. STDMETHODIMP CCiManager::FlushUpdates()
  566. {
  567. SCODE sc = S_OK;
  568. TRY
  569. {
  570. if ( IsShutdown() )
  571. sc = CI_E_SHUTDOWN;
  572. else
  573. _pcci->FlushUpdates();
  574. }
  575. CATCH( CException, e )
  576. {
  577. sc = e.GetErrorCode();
  578. ciDebugOut(( DEB_ERROR,
  579. "FlushUpdates - caught exception 0x%x\n",
  580. sc ));
  581. }
  582. END_CATCH
  583. return sc;
  584. }
  585. //+---------------------------------------------------------------------------
  586. //
  587. // Member: CCiManager::ForceMerge
  588. //
  589. // Synopsis: Forces a master merge on the content index.
  590. //
  591. // Arguments: [mt] -- Merge type (shadow, master, etc.)
  592. //
  593. // Returns: S_OK if successfully forced; error code otherwise.
  594. //
  595. // History: 12-11-96 srikants Created
  596. //
  597. //----------------------------------------------------------------------------
  598. STDMETHODIMP CCiManager::ForceMerge( CI_MERGE_TYPE mt )
  599. {
  600. SCODE sc = S_OK;
  601. if ( 0 != _pcci )
  602. {
  603. Win4Assert( STARTING != _state );
  604. sc = _pcci->ForceMerge( partidDefault, mt );
  605. }
  606. else
  607. {
  608. sc = CI_E_NOT_INITIALIZED;
  609. }
  610. return sc;
  611. }
  612. //+---------------------------------------------------------------------------
  613. //
  614. // Member: CCiManager::AbortMerge
  615. //
  616. // Synopsis: Aborts any in progress merge on the content index.
  617. //
  618. // Returns: S_OK if successfully forced; error code otherwise.
  619. //
  620. // History: 12-11-96 srikants Created
  621. //
  622. //----------------------------------------------------------------------------
  623. STDMETHODIMP CCiManager::AbortMerge()
  624. {
  625. SCODE sc = S_OK;
  626. if ( 0 != _pcci )
  627. {
  628. Win4Assert( STARTING != _state );
  629. sc = _pcci->AbortMerge( partidDefault );
  630. }
  631. else
  632. {
  633. sc = CI_E_NOT_INITIALIZED;
  634. }
  635. return sc;
  636. }
  637. //+---------------------------------------------------------------------------
  638. //
  639. // Member: CCiManager::IsQuiesced
  640. //
  641. // Synopsis: Tests if Content Index is quiesced (no activity). ContentIndex
  642. // is considered quiesced if there are no outstanding documents
  643. // to filter, there is only one index and there are no wordlists.
  644. //
  645. // Arguments: [pfState] - Set to TRUE if it CI is quiesced; FALSE o/w
  646. //
  647. // History: 1-08-97 srikants Created
  648. //
  649. //----------------------------------------------------------------------------
  650. STDMETHODIMP CCiManager::IsQuiesced( BOOL * pfState )
  651. {
  652. Win4Assert( 0 != pfState );
  653. CIF_STATE ciState;
  654. ciState.cbStruct = sizeof ciState;
  655. SCODE sc = GetStatus( &ciState );
  656. if ( S_OK == sc )
  657. {
  658. *pfState = 0 == ciState.eState &&
  659. 0 == ciState.cWordList &&
  660. 0 == ciState.cDocuments &&
  661. 0 == ciState.cFreshTest &&
  662. ciState.cPersistentIndex <= 1;
  663. }
  664. return sc;
  665. }
  666. //
  667. // ICiPersistIncrFile methods
  668. //
  669. //+---------------------------------------------------------------------------
  670. //
  671. // Member: CCiManager::Save
  672. //
  673. // Synopsis: Saves the Content Index data in the directory provided.
  674. // An incremental save for the first time will actually be a full
  675. // save.
  676. //
  677. // Arguments: [pwszSaveDirectory] - The directory in which to save the backup
  678. // data. This directory MUST be on a local drive and security protected.
  679. // It is recommended that this directory has the same security set as the
  680. // current content index directory. Also, it MUST be on a local drive.
  681. // [fFull] - Set to TRUE if a full save is being requested.
  682. // [pIProgressNotify] - Interface to give progress notification.
  683. // [pfAbort] - This flag will be set to TRUE by the caller if
  684. // the caller wants the operation to be aborted before completion.
  685. // [ppWorkidList] - On output, will have the list of changed workids.
  686. // On a full save, this list may be empty in which case the caller must
  687. // assume that all the know workids have changed.
  688. // [ppFileList] - On output, will be set to the filelist enumerator.
  689. // [pfFull] - Set to TRUE if a FULL save was done.
  690. // [pfCallerOwnsFiles] - Set to TRUE if the caller has the responsibility to
  691. // clean up the files.
  692. //
  693. // Returns: S_OK if successful
  694. // Other error code as appropriate.
  695. //
  696. // History: 3-20-97 srikants Created
  697. // 01-Nov-98 KLam Added DiskSpaceToLeave to CiStorage constructor
  698. //
  699. // Notes: Handle DISK_FULL as a special case.
  700. // Right now there is no restartability - if an operation fails in
  701. // the middle due to any problem, the whole operation is aborted
  702. // and the partially created files are deleted. We should do some
  703. // logging to indicate the progress made so far and have a notion of
  704. // restartability. The time I have does not permit doing the
  705. // restartability - SriKants - 3-20-97
  706. //
  707. //----------------------------------------------------------------------------
  708. STDMETHODIMP CCiManager::Save(
  709. const WCHAR *pwszSaveDirectory,
  710. BOOL fFull,
  711. IProgressNotify *pIProgressNotify,
  712. BOOL *pfAbort,
  713. ICiEnumWorkids ** ppWorkidList,
  714. IEnumString ** ppFileList,
  715. BOOL * pfFull,
  716. BOOL * pfCallerOwnsFiles)
  717. {
  718. Win4Assert( !CImpersonateSystem::IsImpersonated() );
  719. if ( !_IsIncrIndexingEnabled() )
  720. return CI_E_INVALID_STATE;
  721. if ( 0 == _pcci )
  722. return CI_E_INVALID_STATE;
  723. if ( IsShutdown() )
  724. return CI_E_SHUTDOWN;
  725. //=====================================
  726. {
  727. //
  728. // There can be only one instance of "Save()" running at
  729. // any time.
  730. //
  731. CLock lock(_mutex);
  732. if ( !_saveTracker.LokIsTracking() )
  733. {
  734. _saveTracker.LokStartTracking( pIProgressNotify, pfAbort );
  735. }
  736. else
  737. {
  738. return CI_E_INVALID_STATE;
  739. }
  740. }
  741. //=====================================
  742. SCODE sc = S_OK;
  743. TRY
  744. {
  745. if ( !_IsValidSaveDirectory( pwszSaveDirectory ) )
  746. {
  747. ciDebugOut(( DEB_ERROR, "Invalid Save Directory (%ws)\n",
  748. pwszSaveDirectory ));
  749. THROW( CException( E_INVALIDARG ) );
  750. }
  751. XInterface<ICiEnumWorkids> xEnumWorkids;
  752. XPtr<CiStorage> xStorage(
  753. new CiStorage( pwszSaveDirectory,
  754. _xAdviseStatus.GetReference(),
  755. _xFrameParams->GetMinDiskSpaceToLeave(),
  756. CURRENT_VERSION_STAMP ));
  757. //
  758. // Until we have a restartable save, nuke all the files in the specified
  759. // directory.
  760. //
  761. xStorage->DeleteAllFiles();
  762. BOOL fIsFull = fFull;
  763. SCODE sc = _pcci->BackupCiData( xStorage.GetReference(),
  764. fIsFull, // in-out parameter
  765. xEnumWorkids,
  766. _saveTracker );
  767. if ( !SUCCEEDED(sc) )
  768. {
  769. THROW( CException(sc) );
  770. }
  771. //
  772. // If we provided the property mapper, we must copy that too.
  773. //
  774. if ( 0 != _pPidLookupTable )
  775. _CreateBackupOfPidTable( xStorage.GetReference(), _saveTracker );
  776. //
  777. // Create an enumerated list of the files created in this save.
  778. //
  779. CEnumString * pEnumStr = new CEnumString;
  780. XInterface<IEnumString> xEnumStr( pEnumStr );
  781. CiStorage::EnumerateFilesInDir( pwszSaveDirectory, *pEnumStr );
  782. //
  783. // Setup the return parameter values.
  784. //
  785. *ppWorkidList = xEnumWorkids.Acquire();
  786. *ppFileList = xEnumStr.Acquire();
  787. *pfFull = fIsFull;
  788. *pfCallerOwnsFiles = TRUE;
  789. }
  790. CATCH( CException,e )
  791. {
  792. ciDebugOut(( DEB_ERROR,
  793. "Error in CCiManager::Save. (0x%X)\n",
  794. e.GetErrorCode() ));
  795. sc = e.GetErrorCode();
  796. }
  797. END_CATCH
  798. //=====================================
  799. {
  800. CLock lock(_mutex);
  801. _saveTracker.LokStopTracking();
  802. }
  803. //=====================================
  804. return sc;
  805. }
  806. // ICiFrameWorkQuery interface - interface that is internal to the
  807. // framework indexing and querying only.
  808. //
  809. //+---------------------------------------------------------------------------
  810. //
  811. // Member: CCiManager::ProcessError
  812. //
  813. // Synopsis: Processes the error code. Only the corruption error is of
  814. // interest to notify the content index which in turn will
  815. // notify the client.
  816. //
  817. // Arguments: [lErrorCode] -
  818. //
  819. // History: 1-08-97 srikants Created
  820. //
  821. //----------------------------------------------------------------------------
  822. STDMETHODIMP CCiManager::ProcessError( long lErrorCode )
  823. {
  824. if ( IsCiCorruptStatus( lErrorCode ) && 0 != _pcci )
  825. _pcci->MarkCorruptIndex();
  826. return S_OK;
  827. }
  828. //
  829. // ISimpleCommandCreator methods
  830. //
  831. //+---------------------------------------------------------------------------
  832. //
  833. // Member: CCiManager::CreateICommand, public
  834. //
  835. // Synopsis: Exposes an ICommand from the framework.
  836. //
  837. // Arguments: [ppiCommand] - Transports back an instance of the ICommand
  838. //
  839. // History: 04-22-97 KrishnaN Created
  840. //
  841. //----------------------------------------------------------------------------
  842. STDMETHODIMP CCiManager::CreateICommand (IUnknown ** ppIUnknown, IUnknown * pOuterUnk)
  843. {
  844. if (0 == ppIUnknown)
  845. {
  846. ciDebugOut((DEB_ERROR, "Invalid ppICommand passed to CCiManager::CreateICommand"));
  847. return E_INVALIDARG;
  848. }
  849. *ppIUnknown = 0;
  850. if ( 0 ==_xDocStore.GetPointer() )
  851. return E_NOINTERFACE;
  852. return MakeLocalICommand(ppIUnknown, _xDocStore.GetPointer(), pOuterUnk);
  853. }
  854. //+---------------------------------------------------------------------------
  855. //
  856. // Member: CCiManager::VerifyCatalog, public
  857. //
  858. // Synopsis: Validate catalog location
  859. //
  860. // Arguments: [pwszMachine] -- Machine on which catalog exists
  861. // [pwszCatalogName] -- Catalog Name
  862. //
  863. // Returns: S_OK for now...
  864. //
  865. // History: 22-Jul-97 KyleP Created
  866. //
  867. //----------------------------------------------------------------------------
  868. SCODE STDMETHODCALLTYPE CCiManager::VerifyCatalog( WCHAR const * pwszMachine,
  869. WCHAR const * pwszCatalogName )
  870. {
  871. return S_OK;
  872. }
  873. //+---------------------------------------------------------------------------
  874. //
  875. // Member: CCiManager::GetDefaultCatalog, public
  876. //
  877. // Synopsis: Determine 'default' catalog for system
  878. //
  879. // Arguments: [pwszCatalogName] -- Catalog Name
  880. // [cwcIn] -- Size in characters of [pwszCatalogName]
  881. // [pcwcOut] -- Size of catalog name
  882. //
  883. // Returns: E_NOTIMPL
  884. //
  885. // History: 22-Jul-97 KyleP Created
  886. //
  887. //----------------------------------------------------------------------------
  888. SCODE STDMETHODCALLTYPE CCiManager::GetDefaultCatalog( WCHAR * pwszCatalogName,
  889. ULONG cwcIn, ULONG * pcwcOut )
  890. {
  891. return E_NOTIMPL;
  892. }
  893. //
  894. // Non-Interface methods
  895. //
  896. void CCiManager::ProcessCiDaemonTermination( SCODE sc )
  897. {
  898. CLock lock(_mutex);
  899. if ( _xDocStore.GetPointer() )
  900. {
  901. _state = READY_TO_FILTER;
  902. sc = _xDocStore->ProcessCiDaemonTermination(sc);
  903. if ( !SUCCEEDED(sc) )
  904. {
  905. ciDebugOut(( DEB_ERROR,
  906. "ICiCDocStore::ProcessCiDaemonTermination returned 0x%X\n",
  907. sc ));
  908. THROW( CException( sc ) );
  909. }
  910. }
  911. }
  912. //+---------------------------------------------------------------------------
  913. //
  914. // Member: CCiManager::_LokCreatePropertyMapper
  915. //
  916. // Synopsis: Creates a property mapper object.
  917. //
  918. // History: 1-31-97 srikants Created
  919. //
  920. //----------------------------------------------------------------------------
  921. IPropertyMapper * CCiManager::_LokCreatePropertyMapper()
  922. {
  923. Win4Assert( 0 == _xPropMapper.GetPointer() );
  924. Win4Assert( 0 == _pPidLookupTable );
  925. XPtr<CPidLookupTable> xPidTable( new CPidLookupTable );
  926. PRcovStorageObj * pObj = _xStorage->QueryPidLookupTable(0);
  927. // Init takes ownership regardless of whether it succeeds.
  928. if ( !xPidTable->Init( pObj ) )
  929. {
  930. ciDebugOut ((DEB_ERROR, "Failed init of PidTable\n"));
  931. THROW (CException(CI_CORRUPT_CATALOG));
  932. }
  933. IPropertyMapper * pMapper = new CFwPropertyMapper( xPidTable.GetReference(),
  934. _fNullContentIndex, // map std props only?
  935. TRUE // Own the pid table
  936. );
  937. _pPidLookupTable = xPidTable.Acquire();
  938. return pMapper;
  939. }
  940. //+---------------------------------------------------------------------------
  941. //
  942. // Member: CCiManager::_CreateBackupOfPidTable
  943. //
  944. // Synopsis: Creates a copy of the pid table.
  945. //
  946. // Arguments: [storage] - Storage to use
  947. // [tracker] - Progress Tracker
  948. //
  949. // History: 3-20-97 srikants Created
  950. //
  951. //----------------------------------------------------------------------------
  952. void CCiManager::_CreateBackupOfPidTable( CiStorage & storage,
  953. PSaveProgressTracker & tracker )
  954. {
  955. Win4Assert( 0 != _pPidLookupTable );
  956. PRcovStorageObj * pObj = storage.QueryPidLookupTable(0);
  957. XPtr<PRcovStorageObj> xObj(pObj);
  958. _pPidLookupTable->MakeBackupCopy( *pObj, tracker );
  959. }
  960. //+---------------------------------------------------------------------------
  961. //
  962. // Member: CCiManager::_UpdateQueryWorkerQueueParams
  963. //
  964. // Synopsis: Updates the worker queue parameters
  965. //
  966. // History: 1-03-97 srikants Created
  967. //
  968. //----------------------------------------------------------------------------
  969. void CCiManager::_UpdateQueryWorkerQueueParams()
  970. {
  971. //
  972. // Getting these from the registry is fine for Indexing Service,
  973. // but will be fixed in the PKM codebase.
  974. //
  975. ULONG cMaxActiveThreads, cMinIdleThreads;
  976. TheWorkQueue.GetWorkQueueRegParams( cMaxActiveThreads,
  977. cMinIdleThreads );
  978. TheWorkQueue.RefreshParams( cMaxActiveThreads, cMinIdleThreads );
  979. }
  980. //+---------------------------------------------------------------------------
  981. //
  982. // Member: CCiManager::UpdDocumentNoThrow
  983. //
  984. // Synopsis: Real worker function that schedules a document for update
  985. // and filtering. This is called directly in push filtering.
  986. //
  987. // Arguments: [pInfo] - Information about the document to be updated.
  988. //
  989. // History: 15-Mar-97 SitaramR Created
  990. //
  991. // Notes: Does not throw because this is simply a worker function
  992. // for UpdateDocument
  993. //
  994. //----------------------------------------------------------------------------
  995. SCODE CCiManager::UpdDocumentNoThrow( const CI_DOCUMENT_UPDATE_INFO * pInfo )
  996. {
  997. Win4Assert( 0 != pInfo );
  998. SCODE sc = S_OK;
  999. TRY
  1000. {
  1001. if ( 0 == _pcci )
  1002. sc = CI_E_NOT_INITIALIZED;
  1003. else
  1004. {
  1005. ULONG hint = _pcci->ReserveUpdate( pInfo->workId );
  1006. ULONG action = CI_UPDATE_OBJ;
  1007. if ( CI_UPDATE_DELETE == pInfo->change )
  1008. action = CI_DELETE_OBJ;
  1009. sc = _pcci->Update( hint,
  1010. pInfo->workId,
  1011. partidDefault,
  1012. pInfo->usn,
  1013. pInfo->volumeId,
  1014. action );
  1015. }
  1016. }
  1017. CATCH( CException,e )
  1018. {
  1019. ciDebugOut(( DEB_ERROR,
  1020. "CCiManager::UpdDocument - Error 0x%X\n",
  1021. e.GetErrorCode() ));
  1022. sc = e.GetErrorCode();
  1023. }
  1024. END_CATCH
  1025. return sc;
  1026. }
  1027. //+---------------------------------------------------------------------------
  1028. //
  1029. // Member: CCiManager::_IsValidLoadDirectory
  1030. //
  1031. // Synopsis: Verifies that the given directory is a valid directory.
  1032. // It ensures that files INDEX.000, INDEX.001, INDEX.002
  1033. // are in the directory.
  1034. //
  1035. // Arguments: [pwszDirPath] - Directory path to verify.
  1036. //
  1037. // Returns: TRUE if valid; FALSE o/w; May throw exceptions.
  1038. //
  1039. // History: 3-21-97 srikants Created
  1040. //
  1041. //----------------------------------------------------------------------------
  1042. BOOL CCiManager::_IsValidSaveDirectory( WCHAR const * pwszDirPath )
  1043. {
  1044. //
  1045. // Confirm that it is a local drive.
  1046. //
  1047. UINT driveType = CiStorage::DetermineDriveType( pwszDirPath );
  1048. if ( DRIVE_FIXED != driveType )
  1049. {
  1050. ciDebugOut(( DEB_ERROR,
  1051. "The given path (%ws) is not a local fixed disk\n",
  1052. pwszDirPath ));
  1053. THROW( CException( E_INVALIDARG ) );
  1054. }
  1055. const MAX_DIR_PATH = MAX_PATH - 13; // Leave room for "\\8.3"
  1056. DWORD dwFileAttributes = GetFileAttributes( pwszDirPath );
  1057. if ( 0xFFFFFFFF == dwFileAttributes )
  1058. return FALSE;
  1059. return dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
  1060. }
  1061. //+---------------------------------------------------------------------------
  1062. //
  1063. // Member: CCiManager::_CompareIncrDataSequence
  1064. //
  1065. // Synopsis: Compares the sequence number information stored in the
  1066. // current catalog and the information in the new files.
  1067. //
  1068. // Arguments: [pwszNewFilesDir] - Directory where the new INDEX.* files
  1069. // are located.
  1070. //
  1071. // Returns: TRUE if they match. FALSE o/w
  1072. //
  1073. // History: 3-19-97 srikants Created
  1074. // 01-Nov-98 KLam Added DiskSpaceToLeave to CiStorage constructor
  1075. //
  1076. //----------------------------------------------------------------------------
  1077. BOOL CCiManager::_CompareIncrDataSequence( WCHAR const * pwszNewFilesDir )
  1078. {
  1079. Win4Assert( !_xStorage.IsNull() );
  1080. //
  1081. // Create a new CiStorage for the target directory.
  1082. //
  1083. XPtr<CiStorage> xStorage(
  1084. new CiStorage( pwszNewFilesDir,
  1085. _xAdviseStatus.GetReference(),
  1086. _xFrameParams->GetMinDiskSpaceToLeave(),
  1087. CURRENT_VERSION_STAMP) );
  1088. //
  1089. // Create the index table for the current storage location.
  1090. //
  1091. CTransaction xact;
  1092. XPtr<CIndexTable> xCurrTable(
  1093. new CIndexTable( _xStorage.GetReference(), xact ));
  1094. XPtr<CIndexTable> xNewTable(
  1095. new CIndexTable( xStorage.GetReference(), xact ));
  1096. unsigned currVersion, newVersion;
  1097. BOOL fFullSave;
  1098. xCurrTable->GetUserHdrInfo( currVersion, fFullSave ); // fFullSave is ignored
  1099. xNewTable->GetUserHdrInfo( newVersion, fFullSave );
  1100. ciDebugOut(( DEB_WARN, "%s\nCurrent Version = %d\n New Version = %d\n",
  1101. fFullSave ? "FullSave" : "Incr. Save",
  1102. currVersion, newVersion ));
  1103. if ( fFullSave )
  1104. {
  1105. //
  1106. // For FULL save, any version is fine.
  1107. return TRUE;
  1108. }
  1109. else
  1110. {
  1111. //
  1112. // For an incremental save, the seqnums in the source and
  1113. // destination must match. Otherwise, it should be ignored.
  1114. //
  1115. return currVersion == newVersion;
  1116. }
  1117. }