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.

940 lines
28 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 2000,
  5. //
  6. // File: MERGE.CXX
  7. //
  8. // Contents: Merge object
  9. //
  10. // Classes: CMerge
  11. //
  12. // History: 13-Nov-91 BartoszM Created
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #include <pstore.hxx>
  18. #include <cifailte.hxx>
  19. #include "merge.hxx"
  20. #include "resman.hxx"
  21. #include "partn.hxx"
  22. #include "mindex.hxx"
  23. #include "mmerglog.hxx"
  24. #include "indxact.hxx"
  25. const unsigned TWO_MEGABYTES = 0x200000;
  26. class CStartMergeTrans : public CTransaction
  27. {
  28. public:
  29. CStartMergeTrans( CMerge & merge ) : _merge(merge)
  30. {
  31. }
  32. ~CStartMergeTrans()
  33. {
  34. if ( GetStatus() != CTransaction::XActCommit)
  35. {
  36. _merge.LokRollBack();
  37. }
  38. }
  39. private:
  40. CMerge & _merge;
  41. };
  42. //+---------------------------------------------------------------------------
  43. //
  44. // Class: XWid
  45. //
  46. // Purpose: Smart Pointer for a workID, destroys it if not acquired
  47. //
  48. // History: 11-Apr-95 DwightKr Created
  49. //
  50. //----------------------------------------------------------------------------
  51. class XWid
  52. {
  53. public:
  54. XWid(WORKID wid, PStorage & storage) : _wid(wid), _storage(storage)
  55. {
  56. }
  57. ~XWid()
  58. {
  59. if (widInvalid != _wid)
  60. _storage.RemoveObject( _wid );
  61. }
  62. WORKID Acquire()
  63. {
  64. WORKID wid=_wid;
  65. _wid=widInvalid;
  66. return wid;
  67. }
  68. private:
  69. WORKID _wid;
  70. PStorage & _storage;
  71. };
  72. //+---------------------------------------------------------------------------
  73. //
  74. // Member: CMerge::CMerge, public
  75. //
  76. // Synopsis: Initializes resources to 0
  77. //
  78. // Arguments: [resman] -- resource manager
  79. // [partid] -- partition id
  80. // [mt] -- merge type
  81. //
  82. // History: 13-Nov-91 BartoszM Created.
  83. //
  84. //----------------------------------------------------------------------------
  85. CMerge::CMerge ( CResManager& resman, PARTITIONID partid, MergeType mt )
  86. : _partid(partid),
  87. _resman(resman),
  88. _pPart(0),
  89. _iidNew(iidInvalid),
  90. _widNewIndex(widInvalid),
  91. _mt(mt),
  92. _indSnap(resman),
  93. _pIndexNew(0),
  94. _aIidOld(0),
  95. _cIidOld(0)
  96. {
  97. }
  98. //+---------------------------------------------------------------------------
  99. //
  100. // Function: LokSetup
  101. //
  102. // Synopsis: Common setup for shadow merge as well as master merge.
  103. // Creates the index snapshot for merge and a wid for the
  104. // new index.
  105. //
  106. // History: 8-30-94 srikants Moved from LokGrabResources as part of
  107. // separating CMerge from CMasterMerge.
  108. //
  109. //----------------------------------------------------------------------------
  110. void CMerge::LokSetup( BOOL fIsMasterMerge )
  111. {
  112. Win4Assert( mtAnnealing == _mt || mtShadow == _mt || mtMaster == _mt
  113. || mtIncrBackup == _mt || mtDeletes == _mt );
  114. // in case this merge was forced
  115. _resman.LokClearForceMerge();
  116. // Get the partition
  117. _pPart = _resman.LokGetPartition(_partid);
  118. // Create unique persisten index id
  119. _iidNew = _pPart->LokMakePersId();
  120. if ( _iidNew == iidInvalid )
  121. {
  122. ciDebugOut (( DEB_ITRACE, "Out of persistent index id's\n" ));
  123. // No real problem. We'll retry merging later once a query frees
  124. // up some indexes.
  125. THROW ( CException ( CI_OUT_OF_INDEX_IDS ));
  126. }
  127. ciFAILTEST( STATUS_NO_MEMORY );
  128. // Initialize source indexes
  129. _indSnap.LokInit( *_pPart, _mt );
  130. if (_indSnap.Count() == 0)
  131. {
  132. return;
  133. }
  134. USN usnMin = 0x100000000i64;
  135. // allocate and initialize array of index id's
  136. _cIidOld = _indSnap.Count();
  137. _aIidOld = new INDEXID [_cIidOld];
  138. for ( unsigned i = 0; i < _cIidOld; i++ )
  139. {
  140. _aIidOld[i] = _indSnap.GetId(i);
  141. if ( _indSnap.GetUsn(i) < usnMin)
  142. {
  143. usnMin = _indSnap.GetUsn(i);
  144. }
  145. }
  146. // create empty persistent index
  147. PStorage::EDefaultStrmType strmType =
  148. fIsMasterMerge ? PStorage::eSparseIndex : PStorage::eNonSparseIndex;
  149. _widNewIndex = _resman._storage.CreateObjectId( _iidNew, strmType );
  150. } //LokSetup
  151. //+---------------------------------------------------------------------------
  152. //
  153. // Member: CMerge::LokGrabResources, public
  154. //
  155. // Synopsis: Initializes all the resources needed to merge
  156. //
  157. // History: 13-Nov-91 BartoszM Created.
  158. //
  159. // Notes: ResMan LOCKED
  160. //
  161. //----------------------------------------------------------------------------
  162. void CMerge::LokGrabResources( )
  163. {
  164. Win4Assert( mtAnnealing == _mt || mtShadow == _mt || mtIncrBackup == _mt ||
  165. mtDeletes == _mt );
  166. // =================================================
  167. CStartMergeTrans xact( *this );
  168. LokSetup( FALSE );
  169. if (_indSnap.Count() == 0)
  170. {
  171. _pPart->FreeIndexId( _iidNew );
  172. return;
  173. }
  174. // a piece of heuristics
  175. unsigned size = _indSnap.TotalSizeInPages();
  176. ciFAILTEST(STATUS_NO_MEMORY);
  177. Win4Assert( 0 == _pIndexNew );
  178. _pIndexNew = new CPersIndex( _resman._storage,
  179. _widNewIndex,
  180. _iidNew,
  181. size,
  182. CDiskIndex::eShadow );
  183. ciFAILTEST(STATUS_NO_MEMORY);
  184. xact.Commit();
  185. // =================================================
  186. } //LokGrabResources
  187. //+---------------------------------------------------------------------------
  188. //
  189. // Member: CMerge::~CMerge, public
  190. //
  191. // Synopsis: Frees resources no longer needed
  192. // (whether merge was successful or not)
  193. //
  194. // History: 13-Nov-91 BartoszM Created.
  195. //
  196. // Notes: ResMan NOT LOCKED
  197. //
  198. //----------------------------------------------------------------------------
  199. CMerge::~CMerge()
  200. {
  201. Win4Assert( 0 == _pIndexNew );
  202. delete _aIidOld;
  203. }
  204. //+---------------------------------------------------------------------------
  205. //
  206. // Member: CMerge::LokRollBack, public
  207. //
  208. // Synopsis: Puts back old indexes into partition, removes
  209. // the new index. Deletes the new index from storage,
  210. // Frees the new index id.
  211. //
  212. // Arguments: [swapped] -- number of old indexes removed from partition
  213. //
  214. // History: 13-Nov-91 BartoszM Created.
  215. //
  216. // Notes: ResMan LOCKED
  217. //
  218. //----------------------------------------------------------------------------
  219. void CMerge::LokRollBack( unsigned swapped )
  220. {
  221. ciDebugOut (( DEB_ITRACE, "Merge::RollBack\n" ));
  222. if ( swapped != 0 )
  223. {
  224. for ( unsigned i=0; i < swapped; i++ )
  225. _pPart->AddIndex ( _indSnap.Get(i) );
  226. if ( swapped == _indSnap.Count() )
  227. _pPart->LokRemoveIndex ( _iidNew );
  228. }
  229. if ( 0 != _pIndexNew )
  230. {
  231. // Delete from storage
  232. _pIndexNew->Remove();
  233. delete _pIndexNew;
  234. _pIndexNew = 0;
  235. }
  236. else if ( widInvalid != _widNewIndex )
  237. {
  238. //
  239. // This can happen if the new index creation fails after
  240. // the wid has been allocated. The wid must be deleted.
  241. //
  242. _resman._storage.RemoveObject( _widNewIndex );
  243. }
  244. if ( _iidNew != iidInvalid )
  245. _pPart->FreeIndexId ( _iidNew );
  246. }
  247. //+---------------------------------------------------------------------------
  248. //
  249. // Member: CMerge::LokZombify, public
  250. //
  251. // Synopsis: Deletes old indexes (they are still in use
  252. // until the destructor of Merge frees them)
  253. //
  254. // History: 13-Nov-91 BartoszM Created.
  255. //
  256. // Notes: ResMan LOCKED
  257. //
  258. //----------------------------------------------------------------------------
  259. void CMerge::LokZombify()
  260. {
  261. for ( unsigned i = 0; i < _indSnap.Count(); i++ )
  262. {
  263. CIndex* pIndex = _indSnap.Get(i);
  264. if ( pIndex != 0 )
  265. {
  266. pIndex->Zombify();
  267. }
  268. }
  269. }
  270. //+---------------------------------------------------------------------------
  271. //
  272. // Member: CMerge::Do, public
  273. //
  274. // Synopsis: Do the merge
  275. //
  276. // Arguments: [mergeProgress] reference to location where % merge complete
  277. // can be stored to update perfmon counters
  278. //
  279. // Signals: CException
  280. //
  281. // History: 13-Nov-91 BartoszM Created.
  282. //
  283. // Notes: ResMan NOT LOCKED
  284. //
  285. //----------------------------------------------------------------------------
  286. void CMerge::Do(CCiFrmPerfCounter & mergeProgress)
  287. {
  288. _pIndexNew->Merge ( _indSnap,
  289. *_pPart,
  290. mergeProgress,
  291. FALSE // no relevant words computation
  292. );
  293. }
  294. //+---------------------------------------------------------------------------
  295. //
  296. // Member: CMasterMerge::LokStoreRestartResources, private
  297. //
  298. // Synopsis: Persistently stores resources needed to restart a master merge.
  299. //
  300. // History: 04-Apr-94 DwightKr Created.
  301. // 23-Aug-94 SrikantS Moved from CMerge.
  302. //
  303. // Notes: ResMan LOCKED
  304. //
  305. //----------------------------------------------------------------------------
  306. void CMasterMerge::LokStoreRestartResources( CDeletedIIDTrans & delIIDTrans )
  307. {
  308. {
  309. PRcovStorageObj *pPersMMergeLog = _resman._storage.QueryMMergeLog(_widMasterLog);
  310. SRcovStorageObj PersMMergeLog( pPersMMergeLog);
  311. //
  312. // Inside kernel, we are guaranteed that a new object has no data in
  313. // it. In user space, we may be using an object that was not deleted
  314. // before due to a failure.
  315. //
  316. PersMMergeLog->InitHeader(_resman.GetStorageVersion()); // reset the header contents
  317. CNewMMergeLog newMMergeLog(*pPersMMergeLog);
  318. unsigned cIndOld = LokCountOld();
  319. INDEXID* aIidOld = LokGetIidList();
  320. for (unsigned i=0; i<cIndOld; i++)
  321. {
  322. CIndexId iid(aIidOld[i]);
  323. newMMergeLog.AddPersistentIndex( iid );
  324. }
  325. newMMergeLog.SetIndexWidMax( _indSnap.MaxWorkId() );
  326. newMMergeLog.SetKeyListWidMax( _resman._sKeyList->MaxWorkId() );
  327. newMMergeLog.Commit();
  328. newMMergeLog.DoCommit();
  329. }
  330. //
  331. // Add new index & master log to index list
  332. //
  333. //
  334. CIndexRecord record;
  335. record._objectId = _widNewIndex;
  336. record._iid = _iidNew;
  337. record._type = itNewMaster;
  338. record._maxWorkId = 0;
  339. //
  340. // The index snap shot belongs to the Partition object after the
  341. // merge information has been committed in the index table.
  342. // Since a memory allocation could fail, we must allocate the
  343. // necessary memory before committing the start of master merge.
  344. //
  345. CIndexSnapshot * pMergeIndSnap = new CIndexSnapshot( _resman );
  346. SIndexSnapshot sMergeIndSnap( pMergeIndSnap );
  347. sMergeIndSnap->LokTakeIndexes( _indSnap );
  348. ciFAILTEST( STATUS_NO_MEMORY );
  349. //
  350. // Commit the beginning of a new master merge in the index table.
  351. //
  352. _resman._idxTab->AddMMergeObjects( _pPart->GetId(),
  353. record,
  354. _widMasterLog,
  355. _widKeyList,
  356. delIIDTrans.GetOldDelIID(),
  357. delIIDTrans.GetNewDelIID()
  358. );
  359. //
  360. // Commit the starting of a new master merge by storing the
  361. // wids and iids in-memory.
  362. //
  363. delIIDTrans.Commit();
  364. _resman._storage.SetSpecialItObjectId( itMMKeyList, _widKeyList );
  365. _pPart->SetMMergeObjectIds( _widMasterLog,
  366. _widNewIndex,
  367. _widCurrentMaster
  368. );
  369. _pPart->RegisterId( _iidNew );
  370. _pPart->SetNewMasterIid( _iidNew );
  371. //
  372. // Mark all the indexes participating in the master merge in memory
  373. // to prevent them from being used for another shadow merge.
  374. //
  375. unsigned cInd;
  376. CIndex** apIndex = sMergeIndSnap->LokGetIndexes( cInd );
  377. for ( unsigned i = 0; i < cInd; i++ )
  378. {
  379. apIndex[i]->SetInMasterMerge();
  380. }
  381. //
  382. // Transfer the ownership of the merge index snapshot to the partition
  383. // object. The ownership will be taken over by the MasterMergeIndex
  384. // when it is created. Once the beginning of a master merge is
  385. // committed, the index snapshot MUST survive until it completes.
  386. // Until a CMasterMergeIndex is created, the partition object will be
  387. // the owner of this index snapshot.
  388. //
  389. _pPart->TakeMMergeIndSnap( sMergeIndSnap.Acquire() );
  390. }
  391. //+---------------------------------------------------------------------------
  392. //
  393. // Member: CMerge::LokLoadRestartResources
  394. //
  395. // Synopsis: Loads restart resources needed to restart a master merge.
  396. //
  397. // History: 04-Apr-94 DwightKr Created.
  398. // 23-Aug-94 SrikantS Moved from CMerge.
  399. //
  400. // Notes: ResMan LOCKED
  401. //
  402. //----------------------------------------------------------------------------
  403. void CMasterMerge::LokLoadRestartResources()
  404. {
  405. // in case this merge was forced
  406. _resman.LokClearForceMerge();
  407. _pPart = _resman.LokGetPartition(_partid);
  408. _mt = mtMaster;
  409. _fSoftAbort = TRUE; // if there is a failure, only a soft abort
  410. // must be done.
  411. // =================================================
  412. CStartMergeTrans xact( *this );
  413. #ifdef KEYLIST_ENABLED
  414. _widKeyList = _resman._storage.GetSpecialItObjectId( itMMKeyList );
  415. Win4Assert( widInvalid != _widKeyList );
  416. #endif // !KEYLIST_ENABLED
  417. _pPart->GetMMergeObjectIds( _widMasterLog,
  418. _widNewIndex,
  419. _widCurrentMaster
  420. );
  421. //
  422. // Restore the list of index participating in this merge into the indSnap
  423. // object.
  424. //
  425. {
  426. PRcovStorageObj *pLog = _resman._storage.QueryMMergeLog(_widMasterLog);
  427. SRcovStorageObj SLog(pLog);
  428. //
  429. // Since this is a restarted master merge, there is no need to
  430. // get the merge indexes. Just get a fresh test.
  431. //
  432. _indSnap.LokInitFreshTest();
  433. {
  434. //
  435. // Create the key list which was being built along with the index.
  436. //
  437. XPtr<CMMergeLog> xMMergeLog( new CMMergeLog( *pLog ) );
  438. //
  439. // We should use the minimum key of key list and index split
  440. // keys as the split key for the key list.
  441. //
  442. CKeyBuf * pKeyLstSplitKey = new CKeyBuf();
  443. SKeyBuf sKeyLstSplitKey(pKeyLstSplitKey);
  444. BitOffset beginBitOff;
  445. BitOffset endBitOff;
  446. CKeyBuf * pIdxSplitKey = new CKeyBuf();
  447. SKeyBuf sIdxSplitKey(pIdxSplitKey);
  448. xMMergeLog->GetKeyListSplitKeyInfo( *pKeyLstSplitKey,
  449. beginBitOff,
  450. endBitOff );
  451. xMMergeLog->GetIdxSplitKeyInfo( *pIdxSplitKey,
  452. beginBitOff,
  453. endBitOff );
  454. if ( pIdxSplitKey->IsMinKey() ||
  455. pKeyLstSplitKey->Compare( *pIdxSplitKey ) > 0 )
  456. {
  457. *pKeyLstSplitKey = *pIdxSplitKey;
  458. }
  459. INDEXID iidNew = _resman._sKeyList->GetNextIid();
  460. #ifdef KEYLIST_ENABLED
  461. _widKeyList = iidNew;
  462. _pNewKeyList = new CWKeyList( _resman._storage,
  463. _widKeyList,
  464. iidNew,
  465. _resman._sKeyList.GetPointer(),
  466. *pKeyLstSplitKey,
  467. xMMergeLog->GetKeyListWidMax() );
  468. #else // KEYLIST_ENABLED
  469. _pNewKeyList = new CWKeyList( 0, iidNew );
  470. #endif // !KEYLIST_ENABLED
  471. }
  472. }
  473. //
  474. // Create or get the target master index.
  475. //
  476. CMasterMergeIndex * pIndexNew = LokCreateOrFindNewMaster();
  477. Win4Assert( 0 == _indSnap.Count() );
  478. CIndexSnapshot & indSnap = pIndexNew->LokGetIndSnap();
  479. Win4Assert( 0 != &indSnap );
  480. //
  481. // allocate and initialize array of index id's
  482. //
  483. _cIidOld = indSnap.Count();
  484. _aIidOld = new INDEXID [_cIidOld];
  485. for ( unsigned i = 0; i < _cIidOld; i++ )
  486. {
  487. _aIidOld[i] = indSnap.GetId(i);
  488. }
  489. xact.Commit();
  490. // =================================================
  491. }
  492. //+---------------------------------------------------------------------------
  493. //
  494. // Member: CMasterMerge::LokGrabResources, public
  495. //
  496. // Synopsis: Initializes all the resources needed to merge
  497. //
  498. // History: 13-Nov-91 BartoszM Created.
  499. // 23-Aug-94 SrikantS ReWrote for CMasterMerge.
  500. //
  501. // Notes: ResMan LOCKED
  502. //
  503. //----------------------------------------------------------------------------
  504. void CMasterMerge::LokGrabResources( CDeletedIIDTrans & delIIDTrans )
  505. {
  506. Win4Assert( mtMaster == _mt );
  507. // =================================================
  508. CStartMergeTrans xact( *this );
  509. LokSetup( TRUE );
  510. if (_indSnap.Count() == 0)
  511. {
  512. return;
  513. }
  514. Win4Assert( !_fSoftAbort );
  515. {
  516. WORKID widDummy;
  517. _pPart->GetMMergeObjectIds(widDummy, widDummy, _widCurrentMaster);
  518. INDEXID iidNewKeyList = _resman._sKeyList->GetNextIid();
  519. //
  520. // For down-level, the ObjectId for logs like the master merge log,
  521. // change log, etc are formed by concatenating the "it" value to
  522. // the partition-id.
  523. //
  524. CIndexId iidMMLog( itMMLog, _partid );
  525. _widMasterLog = (INDEXID) iidMMLog;
  526. XWid xWidMasterLog( _widMasterLog, _resman._storage );
  527. #ifdef KEYLIST_ENABLED
  528. _widKeyList = (INDEXID) iidNewKeyList;
  529. XWid xWidKeyList( _widKeyList, _resman._storage );
  530. #endif // KEYLIST_ENABLED
  531. _resman._storage.InitRcovObj(_widMasterLog, FALSE);
  532. //
  533. // Ideally, this should be the order of steps:
  534. // 1. Create the KeyList and the New Master Index
  535. // 2. Store the master merge state.
  536. //
  537. // However, OFS imposes an ordering on the opening of objects.
  538. // We cannot open the IndexTable object for write access when
  539. // we have other ci objects (like an index or keylist) opened
  540. // for write access in the same thread.
  541. //
  542. // Because of this restriction, we have to update the index table
  543. // first which means we must be able to tolerate failures after
  544. // we have committed the start of a master merge in the index
  545. // table.
  546. //
  547. {
  548. #ifdef KEYLIST_ENABLED
  549. //
  550. // We don't want the creation of key list to fail after
  551. // we have created the index and hash streams and before
  552. // we have created the directory stream. So, first try to
  553. // create the entire key list object and if it succeeds we
  554. // don't have to deal with a partially constructed key list.
  555. //
  556. CWKeyList * pNewKeyList = new CWKeyList ( _resman._storage,
  557. _widKeyList,
  558. iidNewKeyList,
  559. _resman._sKeyList->Size(),
  560. _resman._sKeyList.GetPointer() ); //approx of size
  561. //
  562. // We must delete is here. O/W inversion of priority levels
  563. // will cause a deadlock in OFS.
  564. //
  565. delete pNewKeyList;
  566. #endif // KEYLIST_ENABLED
  567. //
  568. // Pre-Create the master index with all the streams to deal
  569. // with the possibility of failing after committing the start
  570. // of a master merge but before we succeeded in creating all
  571. // the streams. On a restart, the master merge index EXPECTS
  572. // to find all the necessary streams (index/dir).
  573. //
  574. // Create the new index with a size of 64k. This
  575. // reduces the free disk space required for a master merge to
  576. // approximately 64k. We'll be decommiting (shrink from front)
  577. // the old master index as the merge progress.
  578. //
  579. // Note that the initial size is in 4k CI pages.
  580. //
  581. unsigned c4kPages = 65536 / 4096; // 16
  582. ciDebugOut(( DEB_ITRACE,
  583. "creating new master index of size 0x%x bytes\n",
  584. c4kPages * 4096 ));
  585. CPersIndex * pIndex = new CPersIndex( _resman._storage,
  586. _widNewIndex,
  587. _iidNew,
  588. c4kPages,
  589. CDiskIndex::eMaster );
  590. delete pIndex;
  591. }
  592. ciFAILTEST(STATUS_NO_MEMORY);
  593. //
  594. // Store the master merge state.
  595. //
  596. LokStoreRestartResources( delIIDTrans );
  597. //
  598. // Acquire the master log & keylist wids so that they are NOT deleted
  599. // from disk if an exception occurs. Once LokStoreRestartResources()
  600. // completes, any future exceptions should cause the merge to restart
  601. // from a 'paused' condition.
  602. //
  603. xWidMasterLog.Acquire();
  604. #ifdef KEYLIST_ENABLED
  605. xWidKeyList.Acquire();
  606. #endif // KEYLIST_ENABLED
  607. _fSoftAbort = TRUE;
  608. ciFAILTEST(STATUS_NO_MEMORY);
  609. //
  610. // After this point we are in a master merge and any failure
  611. // must be tolerated. Create a new master index. If there is a
  612. // failure while creating the in-memory structure, it can be created
  613. // later when merge is re-attempted.
  614. //
  615. LokCreateOrFindNewMaster();
  616. ciFAILTEST(STATUS_NO_MEMORY);
  617. #ifdef KEYLIST_ENABLED
  618. //
  619. // Open the pre-created keylist.
  620. //
  621. CKeyBuf * pKeyLstSplitKey = new CKeyBuf();
  622. SKeyBuf sKeyLstSplitKey(pKeyLstSplitKey);
  623. pKeyLstSplitKey->FillMin();
  624. _pNewKeyList = new CWKeyList ( _resman._storage,
  625. _widKeyList,
  626. iidNewKeyList,
  627. _resman._sKeyList.GetPointer(),
  628. *pKeyLstSplitKey,
  629. _resman._sKeyList->MaxWorkId()
  630. );
  631. #else
  632. _pNewKeyList = new CWKeyList(
  633. 0,
  634. iidNewKeyList);
  635. #endif // KEYLIST_ENABLED
  636. }
  637. ciFAILTEST(STATUS_NO_MEMORY);
  638. xact.Commit();
  639. }
  640. void CMasterMerge::Do(CCiFrmPerfCounter & mergeProgress)
  641. {
  642. CMasterMergeIndex * pIndexNew = (CMasterMergeIndex *)_pIndexNew;
  643. pIndexNew->Merge ( _pNewKeyList,
  644. _indSnap.GetFresh(),
  645. *_pPart,
  646. mergeProgress,
  647. _resman.GetRegParams(),
  648. TRUE // Compute Relevant Words
  649. );
  650. }
  651. CMasterMerge::~CMasterMerge()
  652. {
  653. Win4Assert( 0 == _pNewKeyList );
  654. }
  655. //+---------------------------------------------------------------------------
  656. //
  657. // Function: LokRollBack
  658. //
  659. // Synopsis: Rollsback a "paused" or "aborted" master merge. A master
  660. // merge is aborted only if it fails before it has been
  661. // recorded in the index table. Once the start has been
  662. // committted, it can only be "paused" and must be restarted
  663. // later. If _fSoftAbort is TRUE, then we have already committed
  664. // the start of master merge and should do a soft abort only.
  665. //
  666. // Arguments: [swapped] --
  667. //
  668. // History: 8-30-94 srikants Created
  669. //
  670. // Notes:
  671. //
  672. //----------------------------------------------------------------------------
  673. void CMasterMerge::LokRollBack( unsigned swapped )
  674. {
  675. if ( _pNewKeyList )
  676. {
  677. #if KEYLIST_ENABLED
  678. if ( !_fSoftAbort )
  679. _pNewKeyList->Remove();
  680. #endif // KEYLIST_ENABLED
  681. delete _pNewKeyList;
  682. _pNewKeyList = 0;
  683. }
  684. if ( _fSoftAbort )
  685. {
  686. _pIndexNew = 0;
  687. return;
  688. }
  689. //
  690. // It is not a soft abort. Must completely abort the master merge.
  691. //
  692. CMerge::LokRollBack( swapped );
  693. }
  694. //+---------------------------------------------------------------------------
  695. //
  696. // Function: LokCreateOrFindNewMaster
  697. //
  698. // Synopsis: This routine either "creates" a new CMasterMergeIndex if
  699. // one doesn't already exist or use an existing one if it
  700. // already exists in the partition.
  701. //
  702. // History: 8-30-94 srikants Moved and adapted from CMerge.
  703. //
  704. // Notes:
  705. //
  706. //----------------------------------------------------------------------------
  707. CMasterMergeIndex * CMasterMerge::LokCreateOrFindNewMaster()
  708. {
  709. Win4Assert( 0 == _pIndexNew );
  710. CPersIndex * pCurrentMasterIndex = _pPart->GetCurrentMasterIndex();
  711. _iidNew = _pPart->GetNewMasterIid();
  712. CMasterMergeIndex * pIndexNew = 0;
  713. if ( 0 != pCurrentMasterIndex &&
  714. pCurrentMasterIndex->GetId() == _iidNew )
  715. {
  716. //
  717. // The New Master Index already exists and has been given
  718. // to the partition. We should use that.
  719. //
  720. Win4Assert( _pPart->GetOldMasterIndex() != pCurrentMasterIndex );
  721. _pIndexNew = pCurrentMasterIndex;
  722. pIndexNew = (CMasterMergeIndex *)_pIndexNew;
  723. }
  724. else
  725. {
  726. CIndexSnapshot * pMergeIndSnap = _pPart->GetMMergeIndSnap();
  727. Win4Assert( 0 != pMergeIndSnap );
  728. //
  729. // The indexid of the new master index is different from the
  730. // current master index (if one exists). So, we are restarting
  731. // a stopped master merge which failed before the new master
  732. // index was created.
  733. //
  734. pIndexNew = new CMasterMergeIndex( _resman._storage,
  735. _widNewIndex,
  736. _iidNew,
  737. pMergeIndSnap->MaxWorkId(),
  738. pCurrentMasterIndex,
  739. _widMasterLog );
  740. _pIndexNew = pIndexNew;
  741. pIndexNew->SetMMergeIndSnap( _pPart->AcquireMMergeIndSnap() );
  742. _pPart->AddIndex ( _pIndexNew );
  743. if ( 0 != pCurrentMasterIndex )
  744. {
  745. _pPart->LokRemoveIndex( pCurrentMasterIndex->GetId() );
  746. _pPart->SetOldMasterIndex( pCurrentMasterIndex );
  747. }
  748. Win4Assert( _pIndexNew->IsMaster() );
  749. Win4Assert( _pPart->GetCurrentMasterIndex() == _pIndexNew );
  750. }
  751. return pIndexNew;
  752. } //LokCreateOrFindNewMaster
  753. //+---------------------------------------------------------------------------
  754. //
  755. // Function: LokTakeIndexes
  756. //
  757. // Synopsis: Takes ownership of the merge indexes from the
  758. // CMasterMergeIndex. This is done at the end to complete the
  759. // commitment of the master merge and the indexsnapshot in the
  760. // merge object should have all the indexes that participated
  761. // in the merge.
  762. //
  763. // Arguments: [pMaster] -- Pointer to the CMasterMergeIndex.
  764. //
  765. // History: 9-29-94 srikants Created
  766. //
  767. // Notes:
  768. //
  769. //----------------------------------------------------------------------------
  770. void CMasterMerge::LokTakeIndexes( CMasterMergeIndex * pMaster )
  771. {
  772. _indSnap.LokTakeIndexes( pMaster->LokGetIndSnap() );
  773. }