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.

442 lines
12 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: mmerglog.cxx
  7. //
  8. // Contents: Implementation of the master merge log.
  9. //
  10. // Classes: CMMergeLog, CNewMMergeLog, CMMergeIdxIter
  11. //
  12. // Functions:
  13. //
  14. // History: 3-30-94 srikants Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <pch.cxx>
  18. #pragma hdrstop
  19. #include <eventlog.hxx>
  20. #include "mmerglog.hxx"
  21. IMPL_DYNARRAY_INPLACE(CIndexIdArray, CIndexId );
  22. //+---------------------------------------------------------------------------
  23. //
  24. // Function: CMMergeIndexList constructor
  25. //
  26. // Synopsis: A dynamic index array.
  27. //
  28. // Arguments: [cShadowIndex] -- Initial guess of number of indexes likely
  29. // to be added to the list.
  30. //
  31. // History: 4-20-94 srikants Created
  32. //
  33. // Notes:
  34. //
  35. //----------------------------------------------------------------------------
  36. CMMergeIndexList::CMMergeIndexList( ULONG cShadowIndex )
  37. : _aShadowIndex( cShadowIndex ), _cShadowIndex(0), _sigIdxList(sigIdxList)
  38. {
  39. }
  40. //+---------------------------------------------------------------------------
  41. //
  42. // Function: GetIndex
  43. //
  44. // Synopsis: Given the "offset" into the indexlist(array), it returns
  45. // the "indexId" in that offset.
  46. //
  47. // Arguments: [iid] -- Output - will have the indexid.
  48. // [nIdx] -- Offset into the array.
  49. //
  50. // Returns: if the specified offset is within the range. FALSE o/w.
  51. //
  52. // History: 4-20-94 srikants Created
  53. //
  54. // Notes:
  55. //
  56. //----------------------------------------------------------------------------
  57. BOOL CMMergeIndexList::GetIndex( CIndexId & iid, ULONG nIdx )
  58. {
  59. if ( nIdx >= _cShadowIndex )
  60. {
  61. return(FALSE);
  62. }
  63. iid = _aShadowIndex.Get(nIdx);
  64. return(TRUE);
  65. }
  66. void CMMergeIndexList::AddIndex( CIndexId & iid )
  67. {
  68. _aShadowIndex.Add( iid, _cShadowIndex );
  69. _cShadowIndex++;
  70. }
  71. //+---------------------------------------------------------------------------
  72. //
  73. // Function: Serialize
  74. //
  75. // Synopsis: Serializes the index list using the given write transaction.
  76. //
  77. // Arguments: [trans] -- Write transaction of which this is part of.
  78. //
  79. // History: 4-20-94 srikants Created
  80. //
  81. // Notes:
  82. //
  83. //----------------------------------------------------------------------------
  84. void CMMergeIndexList::Serialize( CRcovStrmWriteTrans & trans )
  85. {
  86. //
  87. // First write the signature and the count of shadow indexes.
  88. //
  89. ciAssert( _sigIdxList == sigIdxList );
  90. trans.Empty();
  91. trans.Append( this, OFFSET(CMMergeIndexList, _aShadowIndex) );
  92. //
  93. // Now append the shadow index ids that are participating in the
  94. // master merge.
  95. //
  96. for ( ULONG i = 0; i < _cShadowIndex; i++ )
  97. {
  98. CIndexId & iid = _aShadowIndex.Get(i);
  99. trans.Append( &iid, sizeof(CIndexId) );
  100. }
  101. }
  102. void CMMergeIndexList::DeSerialize( CRcovStrmReadTrans & trans,
  103. PRcovStorageObj & obj )
  104. {
  105. //
  106. // Rewind and read the signature and count of shadow indexes
  107. // participating in the master merge.
  108. //
  109. trans.Seek(0);
  110. ULONG cbValid = obj.GetHeader().GetUserDataSize(
  111. obj.GetHeader().GetPrimary() );
  112. ULONG cbMin = OFFSET(CMMergeIndexList, _aShadowIndex);
  113. if ( cbValid < cbMin )
  114. {
  115. ciDebugOut(( DEB_ERROR,
  116. "Master Log Size is Invalid - 0x%X\n", cbValid ));
  117. PStorage & storage = obj.GetStorage();
  118. Win4Assert( !"Corrupt master merge log" );
  119. storage.ReportCorruptComponent( L"MMergeIndexList1" );
  120. THROW( CException( CI_CORRUPT_DATABASE ) );
  121. }
  122. //
  123. // Read the signature and the count of shadow indexes participating
  124. // in the master merge.
  125. //
  126. trans.Read( this, OFFSET(CMMergeIndexList, _aShadowIndex) );
  127. if ( _sigIdxList != sigIdxList )
  128. {
  129. ciDebugOut(( DEB_ERROR,
  130. "Master Log Signature Invalid 0x%X\n", _sigIdxList ));
  131. PStorage & storage = obj.GetStorage();
  132. Win4Assert( !"Corrupt master merge log" );
  133. storage.ReportCorruptComponent( L"MMergeIndexList2" );
  134. THROW( CException( CI_CORRUPT_DATABASE ) );
  135. }
  136. cbMin += sizeof(CIndexId) * _cShadowIndex;
  137. if ( cbValid < cbMin )
  138. {
  139. ciDebugOut(( DEB_ERROR,
  140. "Master Log Size is Invalid - 0x%X\n", cbValid ));
  141. PStorage & storage = obj.GetStorage();
  142. Win4Assert( !"Corrupt master merge log" );
  143. storage.ReportCorruptComponent( L"MMergeIndexList3" );
  144. THROW( CException( CI_CORRUPT_DATABASE ) );
  145. }
  146. for ( ULONG i = 0; i < _cShadowIndex; i++ )
  147. {
  148. CIndexId iid;
  149. trans.Read( &iid, sizeof(CIndexId) );
  150. _aShadowIndex.Add(iid, i );
  151. }
  152. return;
  153. }
  154. //+---------------------------------------------------------------------------
  155. //
  156. // Function: CNewMMergeLog - constructor
  157. //
  158. // Synopsis: Constructor for a new master merge log.
  159. //
  160. // Arguments: [objMMLog] -- The recoverable storage object for the master
  161. // merge log.
  162. //
  163. // History: 4-20-94 srikants Created
  164. //
  165. //----------------------------------------------------------------------------
  166. CNewMMergeLog::CNewMMergeLog( PRcovStorageObj & objMMLog )
  167. :_fCommit(FALSE),
  168. _objMMLog(objMMLog),
  169. _trans(_objMMLog)
  170. {
  171. }
  172. void CNewMMergeLog::DoCommit()
  173. {
  174. if ( _fCommit )
  175. {
  176. _fCommit = FALSE; // To prevent cycles if there is a failure in
  177. // the process of committing.
  178. //
  179. // Write the list of shadow indexes followed by the split key
  180. //
  181. _shadowIdxList.Serialize( _trans );
  182. AppendEmptySplitKeys();
  183. //
  184. // Write the header information and commit the transaction.
  185. //
  186. WriteHeader();
  187. _trans.Commit();
  188. }
  189. }
  190. CNewMMergeLog::~CNewMMergeLog()
  191. {
  192. if ( _fCommit )
  193. {
  194. ciDebugOut(( DEB_ERROR, "aborting committed CNewMMergeLog!\n" ));
  195. }
  196. }
  197. //+---------------------------------------------------------------------------
  198. //
  199. // Function: AppendEmptySplitKeys
  200. //
  201. // Synopsis: Appends empty split keys for the index list and key list.
  202. //
  203. // History: 4-20-94 srikants Created
  204. //
  205. // Notes:
  206. //
  207. //----------------------------------------------------------------------------
  208. void CNewMMergeLog::AppendEmptySplitKeys()
  209. {
  210. CMMergeSplitKey splitKey;
  211. CKeyBuf key;
  212. key.FillMin();
  213. splitKey.SetKey( key );
  214. ciAssert(
  215. _objMMLog.GetHeader().GetUserDataSize( _objMMLog.GetHeader().GetBackup() ) ==
  216. _shadowIdxList.GetValidLength()
  217. );
  218. _trans.Append( &splitKey, sizeof CMMergeSplitKey );
  219. _trans.Append( &splitKey, sizeof CMMergeSplitKey );
  220. }
  221. //+---------------------------------------------------------------------------
  222. //
  223. // Function: WriteHeader
  224. //
  225. // Synopsis: Writes the header for the new master merge log.
  226. //
  227. // History: 4-20-94 srikants Created
  228. //
  229. // Notes:
  230. //
  231. //----------------------------------------------------------------------------
  232. void CNewMMergeLog::WriteHeader()
  233. {
  234. // STACKSTACK
  235. XPtr<struct CRcovUserHdr> xHdr(new CRcovUserHdr);
  236. RtlZeroMemory( xHdr.GetPointer(), sizeof(CRcovUserHdr) );
  237. ciDebugOut(( DEB_ITRACE,
  238. "Writing Header For New Master Log - cShadowIdx %d - oSplitKey %d\n",
  239. _shadowIdxList.GetShadowIndexCount(),
  240. _shadowIdxList.GetValidLength()
  241. ));
  242. ciDebugOut(( DEB_ITRACE,
  243. "WidMax Index 0x%X WidMax KeyList 0x%X\n",
  244. _widMaxIndex, _widMaxKeyList ));
  245. CMMergeLogHdr * phdrMMLog = (CMMergeLogHdr *) xHdr.GetPointer();
  246. phdrMMLog->Init();
  247. phdrMMLog->SetShadowIndexCount(_shadowIdxList.GetShadowIndexCount());
  248. phdrMMLog->SetSplitKeyOffset(_shadowIdxList.GetValidLength());
  249. phdrMMLog->SetKeyListWidMax( _widMaxKeyList );
  250. phdrMMLog->SetIndexWidMax( _widMaxIndex );
  251. _objMMLog.GetHeader().SetUserHdr( _objMMLog.GetHeader().GetBackup(),
  252. xHdr.GetReference() );
  253. }
  254. //+---------------------------------------------------------------------------
  255. //
  256. // Function: CMMergeLog::CMMergeLog
  257. //
  258. // Synopsis: Constructor for an existing master merge log.
  259. //
  260. // Arguments: [objMMLog] -- Recoverable storage object for the master
  261. // mergelog.
  262. //
  263. // History: 4-20-94 srikants Created
  264. //
  265. //----------------------------------------------------------------------------
  266. CMMergeLog::CMMergeLog( PRcovStorageObj & objMMLog )
  267. : _sigMMergeLog(eSigMMergeLog), _objMMLog(objMMLog)
  268. {
  269. //
  270. // Create a read transaction for reading in the master log.
  271. //
  272. CRcovStrmReadTrans trans(_objMMLog);
  273. XPtr<struct CRcovUserHdr> xHdr(new CRcovUserHdr);
  274. CMMergeLogHdr * phdrMMLog = (CMMergeLogHdr *) xHdr.GetPointer();
  275. _objMMLog.GetHeader().GetUserHdr( _objMMLog.GetHeader().GetPrimary(),
  276. xHdr.GetReference() );
  277. _widMaxIndex = phdrMMLog->GetIndexWidMax();
  278. _widMaxKeyList = phdrMMLog->GetKeyListWidMax();
  279. ciDebugOut(( DEB_ITRACE,
  280. "DeSerialize MMLog Hdr - Index Max Wid 0x%X KeyList MaxWid 0x%X\n",
  281. _widMaxIndex, _widMaxKeyList ));
  282. ciDebugOut(( DEB_ITRACE,
  283. "Seeking to 0x%X bytes to read split key\n",
  284. phdrMMLog->GetSplitKeyOffset() ));
  285. //
  286. // Read the index split key.
  287. //
  288. trans.Seek( phdrMMLog->GetSplitKeyOffset() );
  289. trans.Read( &_idxSplitKey, sizeof(_idxSplitKey) );
  290. Win4Assert( _idxSplitKey.IsValid() );
  291. if ( !_idxSplitKey.IsValid() )
  292. {
  293. PStorage & storage = objMMLog.GetStorage();
  294. storage.ReportCorruptComponent( L"MMergeLogSplitKey" );
  295. THROW( CException( CI_CORRUPT_DATABASE ) );
  296. }
  297. //
  298. // Read the keylist split key.
  299. //
  300. trans.Read(&_keylstSplitKey, sizeof(_keylstSplitKey));
  301. Win4Assert( _keylstSplitKey.IsValid() );
  302. if ( !_keylstSplitKey.IsValid() )
  303. {
  304. PStorage & storage = objMMLog.GetStorage();
  305. storage.ReportCorruptComponent( L"MMergeLogKeylstSplitKey" );
  306. THROW( CException( CI_CORRUPT_DATABASE ) );
  307. }
  308. } //CMMergeLog
  309. //+---------------------------------------------------------------------------
  310. //
  311. // Function: CheckPoint
  312. //
  313. // Synopsis: Writes out the state of master merge (as indicated in the
  314. // master log object) to disk in an atomic fashion.
  315. //
  316. // History: 4-20-94 srikants Created
  317. //
  318. //----------------------------------------------------------------------------
  319. void CMMergeLog::CheckPoint()
  320. {
  321. CRcovStrmWriteTrans trans(_objMMLog);
  322. // STACKSTACK
  323. XPtr<struct CRcovUserHdr> xHdr(new CRcovUserHdr);
  324. CMMergeLogHdr * phdrMMLog = (CMMergeLogHdr *) xHdr.GetPointer();
  325. _objMMLog.GetHeader().GetUserHdr( _objMMLog.GetHeader().GetBackup(),
  326. xHdr.GetReference() );
  327. phdrMMLog->SetIndexWidMax( _widMaxIndex );
  328. phdrMMLog->SetKeyListWidMax( _widMaxKeyList );
  329. ciDebugOut(( DEB_ITRACE,
  330. "Seeking to 0x%X bytes to write split key\n",
  331. phdrMMLog->GetSplitKeyOffset() ));
  332. _objMMLog.GetHeader().SetUserHdr( _objMMLog.GetHeader().GetBackup(),
  333. xHdr.GetReference() );
  334. //
  335. // Write out the index split key.
  336. //
  337. trans.Seek( phdrMMLog->GetSplitKeyOffset() );
  338. trans.Write( &_idxSplitKey, sizeof(_idxSplitKey) );
  339. //
  340. // Write out the keylist split key.
  341. //
  342. trans.Write( &_keylstSplitKey, sizeof(_keylstSplitKey) );
  343. trans.Commit();
  344. }
  345. CMMergeIdxListIter::CMMergeIdxListIter( PRcovStorageObj & objMMLog )
  346. : _objMMLog(objMMLog),
  347. _curr(0),
  348. _trans(_objMMLog)
  349. {
  350. _shadowIdxList.DeSerialize( _trans, _objMMLog );
  351. }
  352. BOOL CMMergeIdxListIter::Found( CIndexId & iid )
  353. {
  354. for ( ULONG i = 0; i < _shadowIdxList.GetShadowIndexCount(); i++ )
  355. {
  356. CIndexId iidCurr;
  357. _shadowIdxList.GetIndex( iidCurr , i );
  358. if ( iid == iidCurr )
  359. {
  360. return(TRUE);
  361. }
  362. }
  363. return(FALSE);
  364. }