Source code of Windows XP (NT5)
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.

913 lines
25 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 2001.
  5. //
  6. // File: PARTN.CXX
  7. //
  8. // Contents: Content Index Partition
  9. //
  10. // Classes: CPartition
  11. //
  12. // History: 22-Mar-91 BartoszM Created.
  13. //
  14. // Notes: Unique index ID is created from byte sized per partition
  15. // index ID and Partition ID shifted left by 8.
  16. //
  17. //----------------------------------------------------------------------------
  18. #include <pch.cxx>
  19. #pragma hdrstop
  20. #include <rwex.hxx>
  21. #include <cifailte.hxx>
  22. #include "partn.hxx"
  23. #include "pindex.hxx"
  24. #include "indxact.hxx"
  25. #include "mmerglog.hxx"
  26. #include "mindex.hxx"
  27. #include "resman.hxx"
  28. //+---------------------------------------------------------------------------
  29. //
  30. // Member: CPartition::CPartition, public
  31. //
  32. // Synopsis: Constructor for partition
  33. //
  34. // Arguments:
  35. // [wid] -- wid used for the change log
  36. // [partId] -- partition id
  37. // [storage] -- used to create files
  38. // [frmwrkParams] -- registry params to use
  39. //
  40. // History: 3-Apr-91 BartoszM Created.
  41. //
  42. //----------------------------------------------------------------------------
  43. CPartition::CPartition (
  44. WORKID wid,
  45. PARTITIONID partID,
  46. PStorage& storage,
  47. CCiFrameworkParams & frmwrkParams )
  48. : _sigPartition(eSigPartition),
  49. _frmwrkParams( frmwrkParams ),
  50. _id ( partID ), _queryCount(0), _changes( wid, storage, frmwrkParams ),
  51. _widMasterLog(widInvalid),
  52. _widNewMaster(widInvalid),
  53. _widCurrentMaster(widInvalid),
  54. _widChangeLog(wid),
  55. _iidNewMasterIndex(CIndexId( iidInvalid, partidInvalid ) ),
  56. _pRWStore(0),
  57. _pOldMasterIndex(0),
  58. _pMMergeIndSnap(0),
  59. _storage(storage),
  60. _fCleaningUp(FALSE)
  61. {
  62. // Fill the set of available index id's
  63. _setPersIid.Fill();
  64. _setPersIid.Remove( iidInvalid );
  65. _wlid = MAX_PERS_ID + 1;
  66. }
  67. //+---------------------------------------------------------------------------
  68. //
  69. // Member: CPartition::~CPartition, public
  70. //
  71. // Synopsis: Destructor for partition
  72. //
  73. // History: 4-Apr-91 BartoszM Created.
  74. //
  75. //----------------------------------------------------------------------------
  76. CPartition::~CPartition ()
  77. {
  78. delete _pRWStore;
  79. delete _pMMergeIndSnap;
  80. CIndex* pIndex;
  81. //
  82. // If a MasterMerge is in progress, the master index has an indexsnap
  83. // shot with references to participating indexes. That must be deleted
  84. // first.
  85. //
  86. pIndex = GetCurrentMasterIndex();
  87. if ( 0 != pIndex )
  88. {
  89. _idxlst.Remove( pIndex->GetId() );
  90. delete pIndex;
  91. }
  92. while ( (pIndex = _idxlst.RemoveTop()) != 0 )
  93. {
  94. delete pIndex;
  95. }
  96. }
  97. //+---------------------------------------------------------------------------
  98. //
  99. // Member: CPartition::LokEmpty, public
  100. //
  101. // Synopsis: Initialize a empty partition
  102. //
  103. // History: 14-Nov-94 DwightKr Created.
  104. //
  105. //----------------------------------------------------------------------------
  106. void CPartition::LokEmpty()
  107. {
  108. _widMasterLog = widInvalid;
  109. _widNewMaster = widInvalid;
  110. _widCurrentMaster = widInvalid;
  111. _iidNewMasterIndex = CIndexId( iidInvalid, partidInvalid );
  112. delete _pRWStore;
  113. _pRWStore = NULL;
  114. _pOldMasterIndex = NULL;
  115. delete _pMMergeIndSnap;
  116. _pMMergeIndSnap = NULL;
  117. _changes.LokEmpty();
  118. }
  119. #define _CompUL(x,y) ((*(x)) > (*(y)) ? 1 : (*(x)) == (*(y)) ? 0 : -1)
  120. #define _SwapUL(x,y) { ULONG _t = *(x); *(x) = *(y); *(y) = _t; }
  121. inline static void _AddRootUL(ULONG x,ULONG n,ULONG *p)
  122. {
  123. ULONG _x = x;
  124. ULONG _j = (2 * (_x + 1)) - 1;
  125. while (_j < n)
  126. {
  127. if (((_j + 1) < n) &&
  128. (_CompUL(p + _j,p + _j + 1) < 0))
  129. _j++;
  130. if (_CompUL(p + _x,p + _j) < 0)
  131. {
  132. _SwapUL(p + _x,p + _j);
  133. _x = _j;
  134. _j = (2 * (_j + 1)) - 1;
  135. }
  136. else break;
  137. }
  138. } //_AddRootUL
  139. void SortULongArray(ULONG *pulItems,ULONG cItems)
  140. {
  141. if (cItems == 0)
  142. return;
  143. long z;
  144. for (z = (((long) cItems + 1) / 2) - 1; z >= 0; z--)
  145. {
  146. _AddRootUL(z,cItems,pulItems);
  147. }
  148. for (z = cItems - 1; z != 0; z--)
  149. {
  150. _SwapUL(pulItems,pulItems + z);
  151. _AddRootUL(0,(ULONG) z,pulItems);
  152. }
  153. } //_SortULongArray
  154. //+---------------------------------------------------------------------------
  155. //
  156. // Member: CPartition::LokQueryMergeIndexes, public
  157. //
  158. // Arguments: [count] -- returns count of indexes in the array
  159. // [mt] -- type of merge
  160. //
  161. // Returns: Array of indexes to be merged
  162. //
  163. // History: 4-Apr-91 BartoszM Created.
  164. //
  165. // Notes: ResMan LOCKED
  166. //
  167. //----------------------------------------------------------------------------
  168. CIndex** CPartition::LokQueryMergeIndexes ( unsigned& count, MergeType mt )
  169. {
  170. ciDebugOut (( DEB_ITRACE, "Query %s (%d)\n",
  171. (mt == mtWordlist) ? "wordlists" : "merge indexes",
  172. _idxlst.Count() ));
  173. int cInd = _idxlst.Count();
  174. ciDebugOut (( DEB_ITRACE, " Merge indexes: " ));
  175. CIndex** indexes = new CIndex* [ cInd ];
  176. SByteArray sapIndex( indexes );
  177. unsigned cIndSoFar = 0;
  178. CForIndexIter iter(_idxlst);
  179. if ( mtMaster == mt )
  180. {
  181. //
  182. // Don't include wordlists in a master merge. Must use only
  183. // persistent indexes.
  184. //
  185. for ( ; !_idxlst.AtEnd(iter); _idxlst.Advance(iter) )
  186. {
  187. CIndexId iid = iter->GetId();
  188. if ( iid.IsPersistent() && !iter->IsZombie() )
  189. {
  190. ciDebugOut(( DEB_ITRACE | DEB_NOCOMPNAME, "%lx, ",
  191. iter->GetId() ));
  192. iter->Reference();
  193. indexes[cIndSoFar++] = iter.GetIndex();
  194. }
  195. }
  196. }
  197. else
  198. {
  199. Win4Assert( mtShadow == mt || mtWordlist == mt || mtAnnealing == mt || mtIncrBackup || mtDeletes == mt );
  200. // Get the sizes of all persistent indexes that might be in the merge
  201. ULONG aSizes[ MAX_PERS_ID ];
  202. ULONG cPersistent = 0;
  203. {
  204. CForIndexIter iterSize( _idxlst );
  205. for ( ; !_idxlst.AtEnd( iterSize ); _idxlst.Advance( iterSize ) )
  206. {
  207. if ( !iterSize->IsMaster() && !iterSize->InMasterMerge() )
  208. {
  209. CIndexId iid = iterSize->GetId();
  210. if ( iid.IsPersistent() )
  211. {
  212. ULONG cp = iterSize->Size();
  213. //DbgPrint( " pers index %d is size %#x pages\n", cPersistent, cp );
  214. aSizes[ cPersistent++ ] = cp;
  215. }
  216. }
  217. }
  218. }
  219. // Find the size of the index with 1/3 smaller and 2/3 larger indexes
  220. ULONG aMedian[ MAX_PERS_ID ];
  221. RtlCopyMemory( &aMedian, &aSizes, cPersistent * sizeof ULONG );
  222. SortULongArray( (ULONG *) &aMedian, cPersistent );
  223. ULONG cpAtOneThird = aMedian[ cPersistent / 3 ];
  224. // Wordlists come first in the iteration. Add them all to the merge.
  225. for ( ; !_idxlst.AtEnd(iter); _idxlst.Advance(iter) )
  226. {
  227. CIndexId iid = iter->GetId();
  228. if ( iid.IsPersistent() )
  229. break;
  230. ciDebugOut(( DEB_ITRACE | DEB_NOCOMPNAME, "%lx, ",
  231. iter->GetId() ));
  232. Win4Assert ( !iter->IsZombie() );
  233. iter->Reference();
  234. indexes[cIndSoFar++] = iter.GetIndex();
  235. }
  236. //
  237. // If we are doing a shadow merge, we must not have more than the maximum
  238. // allowed count of indexes - so merge as to have at most that number.
  239. //
  240. if ( mtShadow == mt || mtAnnealing == mt || mtIncrBackup == mt || mtDeletes == mt )
  241. {
  242. unsigned cMaxRemaining;
  243. //
  244. // Count is decremented by 1 to account for the new index that will
  245. // be created.
  246. //
  247. BOOL fAnyPersistent = TRUE;
  248. if ( mtDeletes == mt )
  249. {
  250. cMaxRemaining = _frmwrkParams.GetMaxIndexes() - 1;
  251. }
  252. else if ( mtShadow == mt )
  253. {
  254. cMaxRemaining = 0;
  255. // Don't use any persistent indexes in the merge if
  256. // there are free slots available.
  257. if ( cPersistent < _frmwrkParams.GetMaxIndexes() )
  258. fAnyPersistent = FALSE;
  259. }
  260. else if ( mtAnnealing == mt )
  261. {
  262. cMaxRemaining = _frmwrkParams.GetMaxIdealIndexes() - 1;
  263. }
  264. else
  265. {
  266. cMaxRemaining = 0;
  267. }
  268. ULONG cSoFar = 0;
  269. if ( fAnyPersistent )
  270. {
  271. while ( !_idxlst.AtEnd(iter) && (cInd - cIndSoFar > cMaxRemaining) )
  272. {
  273. CIndexId iid = iter->GetId();
  274. ciDebugOut(( DEB_ITRACE | DEB_NOCOMPNAME, "pers: %lx, ",
  275. iter->GetId() ));
  276. Win4Assert ( !iter->IsZombie() );
  277. if ( !iter->IsMaster() && !iter->InMasterMerge() )
  278. {
  279. //
  280. // We should skip over the master index and indexes
  281. // participating in a master merge for a shadow merge.
  282. // Also skip indexes > 4 times the size of the 1/3 median.
  283. //
  284. if ( ( mtShadow != mt ) ||
  285. ( aSizes[cSoFar] < ( 4 * cpAtOneThird) ) )
  286. {
  287. iter->Reference();
  288. indexes[cIndSoFar++] = iter.GetIndex();
  289. }
  290. cSoFar++;
  291. }
  292. else
  293. {
  294. #if DBG==1
  295. if ( iter->InMasterMerge() )
  296. {
  297. ciDebugOut(( DEB_ITRACE,
  298. "ShadowMergeSet:Skipping over 0x%X - Already in MMergeSet\n",
  299. iter->GetId() ));
  300. }
  301. #endif // DBG==1
  302. }
  303. _idxlst.Advance(iter);
  304. }
  305. }
  306. }
  307. }
  308. count = cIndSoFar;
  309. ciDebugOut (( DEB_ITRACE | DEB_NOCOMPNAME, "\n" ));
  310. sapIndex.Acquire();
  311. return indexes;
  312. } //LokQueryMergeIndexes
  313. //+---------------------------------------------------------------------------
  314. //
  315. // Member: CPartition::LokQueryIndexesForBackup
  316. //
  317. // Synopsis: Snaps persistent indexes for backup. For a full backup, all
  318. // persistent indexes are returned. For an incremental backup,
  319. // only the shadow indexes are returned.
  320. //
  321. // Arguments: [count] - on output, count of indexes
  322. // [fFull] - Flag indicating if it is a full backup.
  323. //
  324. // Returns: Array of pointers to refcounted indexes.
  325. //
  326. // History: 3-18-97 srikants Created
  327. //
  328. //----------------------------------------------------------------------------
  329. CIndex** CPartition::LokQueryIndexesForBackup ( unsigned& count, BOOL fFull )
  330. {
  331. ciDebugOut (( DEB_ITRACE, "LokQueryIndexesForBackup (%s)\n",
  332. fFull ? "Full" : "Incremental" ));
  333. int cInd = _idxlst.Count();
  334. ciDebugOut (( DEB_ITRACE, " Backup indexes: " ));
  335. CIndex** indexes = new CIndex* [ cInd ];
  336. SByteArray sapIndex( indexes );
  337. unsigned cIndSoFar = 0;
  338. CForIndexIter iter(_idxlst);
  339. //
  340. // Don't include wordlists . Must use only persistent indexes.
  341. //
  342. for ( ; !_idxlst.AtEnd(iter); _idxlst.Advance(iter) )
  343. {
  344. CIndexId iid = iter->GetId();
  345. if ( iid.IsPersistent() && !iter->IsZombie() )
  346. {
  347. if ( !fFull && iter.GetIndex()->IsMaster() )
  348. {
  349. //
  350. // For an incremental backup, skip the master index.
  351. //
  352. continue;
  353. }
  354. //
  355. // We should never have an in-progress merge while doing the
  356. // save.
  357. //
  358. Win4Assert( ! iter.GetIndex()->IsMasterMergeIndex() );
  359. ciDebugOut (( DEB_ITRACE | DEB_NOCOMPNAME, "%lx, ",
  360. iter->GetId() ));
  361. iter->Reference();
  362. indexes[cIndSoFar++] = iter.GetIndex();
  363. }
  364. }
  365. count = cIndSoFar;
  366. ciDebugOut (( DEB_ITRACE | DEB_NOCOMPNAME, "\n" ));
  367. sapIndex.Acquire();
  368. return indexes;
  369. }
  370. //+---------------------------------------------------------------------------
  371. //
  372. // Member: CPartition::LokCheckMerge, public
  373. //
  374. // Synopsis: Checks if there is need to merge
  375. //
  376. // Arguments: [mt] -- type of merge
  377. // History: 4-Apr-91 BartoszM Created.
  378. //
  379. // Notes: ResMan LOCKED
  380. //
  381. //----------------------------------------------------------------------------
  382. BOOL CPartition::LokCheckMerge( MergeType mt )
  383. {
  384. if ( mt == mtShadow )
  385. {
  386. ciDebugOut (( DEB_ITRACE, "Partition: check shadow merge\n" ));
  387. if ( _idxlst.CountWlist() >= _frmwrkParams.GetMaxWordlists() )
  388. {
  389. ciDebugOut (( DEB_ITRACE | DEB_PENDING,
  390. "Shadow merge, reason: wordlists %d >= %d \n",
  391. _idxlst.CountWlist(), _frmwrkParams.GetMaxWordlists() ));
  392. return TRUE;
  393. }
  394. if ( LokCheckWordlistMerge() )
  395. {
  396. ciDebugOut(( DEB_ITRACE | DEB_PENDING,
  397. "Shadow merge, reason: wordlist size > %d\n",
  398. _frmwrkParams.GetMinSizeMergeWordlist() ));
  399. return TRUE;
  400. }
  401. }
  402. else if ( mt == mtAnnealing )
  403. {
  404. ciDebugOut (( DEB_ITRACE, "Partition: check annealing merge\n" ));
  405. if ( _idxlst.Count() > _frmwrkParams.GetMaxIdealIndexes() ||
  406. _idxlst.CountWlist() > 0 )
  407. {
  408. ciDebugOut (( DEB_ITRACE | DEB_PENDING,
  409. "Annealing merge, reason: too many indices %d >= %d, %d wordlists \n",
  410. _idxlst.Count(), _frmwrkParams.GetMaxIdealIndexes(), _idxlst.CountWlist() ));
  411. return TRUE;
  412. }
  413. }
  414. return FALSE;
  415. }
  416. //+---------------------------------------------------------------------------
  417. //
  418. // Member: CPartition::LokCheckWordlistMerge, public
  419. //
  420. // Synopsis: Checks if there is need to merge due to excessive wordlist
  421. // memory consumption.
  422. //
  423. // History: 12-Jan-1999 KyleP Created.
  424. //
  425. // Notes: ResMan LOCKED
  426. //
  427. //----------------------------------------------------------------------------
  428. BOOL CPartition::LokCheckWordlistMerge()
  429. {
  430. unsigned size = 0;
  431. for ( CForIndexIter iter (_idxlst);
  432. !_idxlst.AtEnd(iter);
  433. _idxlst.Advance(iter) )
  434. {
  435. CIndexId iid = iter->GetId();
  436. if ( iid.IsPersistent() )
  437. break;
  438. Win4Assert( !iter->IsZombie() );
  439. size += iter.GetIndex()->Size();
  440. }
  441. return ( size > _frmwrkParams.GetMinSizeMergeWordlist() );
  442. }
  443. //+---------------------------------------------------------------------------
  444. //
  445. // Member: CPartition::LokGetIndexes, public
  446. //
  447. // Synopsis: Returns an array of index pointers
  448. //
  449. // Arguments: [cInd] -- count of returned indexes
  450. //
  451. // History: 07-Oct-91 BartoszM Created
  452. //
  453. // Notes: ResMan LOCKED
  454. //
  455. //----------------------------------------------------------------------------
  456. unsigned CPartition::LokGetIndexes ( CIndex** apIndex )
  457. {
  458. ciDebugOut (( DEB_ITRACE, "CPartition::GetIndexes\n" ));
  459. if ( _idxlst.Count() == 0 )
  460. return 0;
  461. unsigned cInd = 0;
  462. for (CForIndexIter iter (_idxlst); !_idxlst.AtEnd(iter); _idxlst.Advance(iter))
  463. {
  464. Win4Assert ( !iter->IsZombie() );
  465. iter->Reference();
  466. apIndex[cInd] = iter.GetIndex();
  467. cInd++ ;
  468. }
  469. return cInd;
  470. }
  471. //+---------------------------------------------------------------------------
  472. //
  473. // Member: CPartition::LokMakeWlstId, public
  474. //
  475. // Synopsis: Return unique volatile index id
  476. //
  477. // History: 12-Apr-91 BartoszM Created.
  478. //
  479. //----------------------------------------------------------------------------
  480. INDEXID CPartition::LokMakeWlstId ()
  481. {
  482. Win4Assert ( _wlid > MAX_PERS_ID );
  483. ULONG hint = _wlid;
  484. CIndexId iid;
  485. for(;;)
  486. {
  487. iid = CIndexId ( hint, _id );
  488. for ( CForIndexIter iter = _idxlst;
  489. !_idxlst.AtEnd(iter);
  490. _idxlst.Advance(iter) )
  491. {
  492. if ( iter->GetId() == iid )
  493. break;
  494. }
  495. hint++;
  496. // wrap around
  497. if ( hint >= MAX_VOL_ID )
  498. hint = MAX_PERS_ID + 1;
  499. Win4Assert ( hint != _wlid );
  500. if (_idxlst.AtEnd(iter) )
  501. break;
  502. }
  503. _wlid = hint;
  504. return iid;
  505. }
  506. //+---------------------------------------------------------------------------
  507. //
  508. // Member: CPartition::LokMakePersId, public
  509. //
  510. // Synopsis: Return unique persistent index id
  511. //
  512. // History: 12-Apr-91 BartoszM Created.
  513. //
  514. // Notes: ResMan LOCKED
  515. //
  516. //----------------------------------------------------------------------------
  517. INDEXID CPartition::LokMakePersId ()
  518. {
  519. int piid = _setPersIid.FirstElement();
  520. if ( piid == EOS )
  521. {
  522. Win4Assert ( piid != EOS );
  523. return iidInvalid;
  524. }
  525. _setPersIid.Remove ( piid );
  526. ciDebugOut (( DEB_ITRACE, "New pers index id %x\n", piid ));
  527. CIndexId iid ( piid, _id );
  528. #if CIDBG==1
  529. //
  530. // There musn't be an index already with the same iid.
  531. //
  532. Win4Assert( 0 == LokGetIndex(iid) && "Adding Duplicate Index" );
  533. #endif // CIDBG==1
  534. return iid;
  535. }
  536. void CPartition::RegisterId ( CIndexId iid )
  537. {
  538. int persid = iid.PersId();
  539. _setPersIid.Remove ( persid );
  540. }
  541. //+---------------------------------------------------------------------------
  542. //
  543. // Member: CPartition::FreeIndexId, public
  544. //
  545. // Synopsis: Recycle index id
  546. //
  547. // History: 08-Oct-91 BartoszM Created.
  548. //
  549. // Notes: ResMan LOCKED
  550. //
  551. //----------------------------------------------------------------------------
  552. void CPartition::FreeIndexId ( CIndexId iid )
  553. {
  554. ciDebugOut (( DEB_ITRACE, "Free index id %lx\n", iid ));
  555. if ( iid.IsPersistent() )
  556. {
  557. int persid = iid.PersId();
  558. _setPersIid.Add ( persid );
  559. }
  560. }
  561. #if CIDBG==1
  562. CIndex * CPartition::LokGetIndex( CIndexId iid)
  563. {
  564. CForIndexIter iter(_idxlst);
  565. for ( ; !_idxlst.AtEnd(iter); _idxlst.Advance(iter) )
  566. {
  567. CIndexId iidCurr = iter->GetId();
  568. if ( iidCurr == iid )
  569. {
  570. return iter.GetIndex();
  571. }
  572. }
  573. return 0;
  574. }
  575. #endif // CIDBG==1
  576. //+---------------------------------------------------------------------------
  577. //
  578. // Member: CPartition::AddIndex, public
  579. //
  580. // Synopsis: Add a newly created index (wordlist)
  581. //
  582. // Arguments: [pIndex] -- index to be added
  583. //
  584. // History: 26-Apr-91 BartoszM Created.
  585. //
  586. // Notes: ResMan LOCKED
  587. //
  588. //----------------------------------------------------------------------------
  589. void CPartition::AddIndex ( CIndex* pIndex )
  590. {
  591. ciDebugOut (( DEB_ITRACE, "Partition: Adding index %lx\n", pIndex->GetId() ));
  592. #if CIDBG==1
  593. //
  594. // This index must not already exist in the list.
  595. //
  596. CIndexId iid = pIndex->GetId();
  597. Win4Assert( 0 == LokGetIndex( iid ) && "Adding Duplicate Index" );
  598. #endif // CIDBG==1
  599. _idxlst.Add ( pIndex );
  600. #ifdef CI_FAILTEST
  601. NTSTATUS status = CI_CORRUPT_DATABASE ;
  602. ciFAILTEST( status );
  603. #endif // CI_FAILTEST
  604. }
  605. //+---------------------------------------------------------------------------
  606. //
  607. // Member: CPartition::Swap, public
  608. //
  609. // Synopsis: Replace old indexes with a new one (after merge)
  610. // Old indexes are removed from the list
  611. // and marked 'deleted' for later deletion
  612. //
  613. // Arguments: [xact] -- transaction
  614. // [pIndexNew] -- index to be added
  615. // [cInd] -- count of indexes to be removed
  616. // [aiidOld] -- indexes to be removed
  617. //
  618. // History: 26-Apr-91 BartoszM Created.
  619. //
  620. // Notes: ResMan LOCKED
  621. //
  622. //----------------------------------------------------------------------------
  623. void CPartition::Swap (
  624. CMergeTrans& xact,
  625. CIndex * pIndexNew,
  626. unsigned cInd,
  627. INDEXID aIidOld[] )
  628. {
  629. ciDebugOut (( DEB_ITRACE, "Partition: Swap in %lx for \n",
  630. pIndexNew->GetId() ));
  631. // Indexes will be deleted when transaction commits
  632. for ( unsigned i = 0; i < cInd; i++ )
  633. {
  634. _idxlst.Remove ( aIidOld[i] );
  635. xact.LogSwap ();
  636. }
  637. //
  638. // The master index was added to the index list at the BEGINNING of the
  639. // master merge. Hence we don't need to add it here.
  640. //
  641. if ( !pIndexNew->IsMaster() )
  642. {
  643. #if CIDBG==1
  644. //
  645. // This index must not already exist in the list.
  646. //
  647. CIndexId iid = pIndexNew->GetId();
  648. Win4Assert( 0 == LokGetIndex( iid ) && "Adding Duplicate Index" );
  649. #endif // CIDBG==1
  650. _idxlst.Add ( pIndexNew );
  651. }
  652. _changes.LokRemoveIndexes ( xact, cInd, aIidOld );
  653. }
  654. //+---------------------------------------------------------------------------
  655. //
  656. // Function: LokQueryMMergeIndexes
  657. //
  658. // Synopsis: Gets the list on indexes participating in the master merge
  659. // based on the list of indexes stored in the master merge log.
  660. //
  661. // Arguments: [count] -- Will have the number of participating
  662. // indexes.
  663. // [objMMLog] -- The Recoverable Storage Object for the master
  664. // merge log.
  665. //
  666. // History: 4-01-94 srikants Created
  667. //
  668. // Notes: The indexes are NOT reference counted here because they
  669. // are expected to have been reference counted during startup.
  670. //
  671. //----------------------------------------------------------------------------
  672. CIndex ** CPartition::LokQueryMMergeIndexes( unsigned & count,
  673. PRcovStorageObj & objMMLog )
  674. {
  675. //
  676. // Iterator for the master log.
  677. //
  678. CMMergeIdxListIter iterMMLog( objMMLog );
  679. count = iterMMLog.Count();
  680. Win4Assert( 0 != count );
  681. CIndex** indexes = new CIndex* [ count ];
  682. SByteArray sapIndex(indexes);
  683. ULONG cIndSoFar = 0;
  684. for ( CForIndexIter iter(_idxlst) ;
  685. !_idxlst.AtEnd(iter); _idxlst.Advance(iter) )
  686. {
  687. CIndexId iid = iter->GetId();
  688. if ( iid.IsPersistent() && iterMMLog.Found( iid) )
  689. {
  690. ciDebugOut (( DEB_ITRACE | DEB_NOCOMPNAME, "%lx, ",
  691. iter->GetId() ));
  692. Win4Assert ( !iter->IsZombie() );
  693. indexes[cIndSoFar++] = iter.GetIndex();
  694. iter->Reference();
  695. iter->SetInMasterMerge();
  696. }
  697. }
  698. Win4Assert( cIndSoFar == count );
  699. sapIndex.Acquire();
  700. return(indexes);
  701. }
  702. void CPartition::SerializeMMergeIndexes( unsigned count,
  703. const CIndex * aIndexes[], PRcovStorageObj & objMMLog )
  704. {
  705. CNewMMergeLog mmLog ( objMMLog );
  706. for ( unsigned i = 0; i < count; i++ )
  707. {
  708. const CIndex * pIndex = aIndexes[i];
  709. Win4Assert( pIndex->IsPersistent() );
  710. CIndexId iid(pIndex->GetId());
  711. mmLog.AddPersistentIndex( iid );
  712. }
  713. mmLog.Commit();
  714. }
  715. //+---------------------------------------------------------------------------
  716. //
  717. // Member: CPartition::GetCurrentMasterIndex, public
  718. //
  719. // Synopsis: Returns the current master index for this partition.
  720. //
  721. // History: 13-Apr-94 DwightKr Created.
  722. //
  723. //----------------------------------------------------------------------------
  724. CPersIndex * CPartition::GetCurrentMasterIndex()
  725. {
  726. for (CForIndexIter iter(_idxlst);
  727. !_idxlst.AtEnd(iter);
  728. _idxlst.Advance(iter)
  729. )
  730. {
  731. if ( iter->IsMaster() )
  732. {
  733. Win4Assert( iter->IsPersistent() );
  734. return (CPersIndex*) iter.GetIndex();
  735. }
  736. }
  737. return 0;
  738. }
  739. //+---------------------------------------------------------------------------
  740. //
  741. // Member: CPartition::LokZombify, public
  742. //
  743. // Synopsis: Zombify all indexes, and delete the MMlog, if any. Ownership
  744. // of the indexes is transferred to the caller.
  745. //
  746. // History: 13-Apr-94 DwightKr Created.
  747. //
  748. //----------------------------------------------------------------------------
  749. CIndex ** CPartition::LokZombify(unsigned & cInd )
  750. {
  751. //
  752. // Get list of current indexes
  753. //
  754. CIndex ** paIndex = new CIndex *[ _idxlst.Count() ];
  755. cInd = LokGetIndexes( paIndex );
  756. //
  757. // Zombify each index, and remove it from the in-memory index list
  758. //
  759. for (unsigned i=0; i<cInd; i++)
  760. {
  761. paIndex[i]->Zombify();
  762. _idxlst.Remove( paIndex[i]->GetId() );
  763. }
  764. return paIndex;
  765. }