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.

418 lines
11 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1998.
  5. //
  6. // File: mmerglog.hxx
  7. //
  8. // Contents: Master Log manipulation class.
  9. //
  10. // Classes: CMMergeLog, CNewMMergeLog, CMMergeIdxListIter
  11. //
  12. // Functions:
  13. //
  14. // History: 3-30-94 srikants Created
  15. //
  16. // Note : The Primary/Backup Streams in the master log have the
  17. // following format.
  18. //
  19. // 4 Bytes - sigIdxList ("MMIL")
  20. // 4 Bytes - Number of shadow indexes participating in the
  21. // master merge.
  22. // 4n Bytes- Where n is the number of shadow indexes in the
  23. // master merge.
  24. //
  25. // This will be the index split key.
  26. //
  27. // 4 Bytes - sigSplitKey ("MMSK")
  28. // 4 Bytes - Number of valid bytes in the SplitKey.
  29. // MAXKEYSIZE Bytes - The index SplitKey.
  30. // 4 Bytes - Property Id of the SplitKey.
  31. // 4 Bytes - PageNumber
  32. // 4 Bytes - Offset within Page Number
  33. //
  34. // This will be the keylist split key.
  35. //
  36. // 4 Bytes - sigSplitKey("MMSK")
  37. // 4 Bytes - Number of valid bytes in the SplitKey.
  38. // MAXKEYSIZE Bytes - The keylist SplitKey.
  39. // 4 Bytes - Property id of the split key.
  40. // 4 Bytes - PageNumber
  41. // 4 Bytes - Offset within Page Number
  42. //
  43. //----------------------------------------------------------------------------
  44. #pragma once
  45. #include <prcstob.hxx>
  46. #include <idxids.hxx>
  47. #include <rcstxact.hxx>
  48. #include <bitoff.hxx>
  49. #ifndef OFFSET
  50. #define OFFSET( CClass, mem ) ((int) (ULONG_PTR)&((CClass *)0)->mem)
  51. #endif // OFFSET
  52. #include <pshpack4.h>
  53. //+---------------------------------------------------------------------------
  54. //
  55. // Class: CMMergeLogHdr
  56. //
  57. // Purpose: Header information stored in the user header portion of
  58. // the MasterMergeLog.
  59. //
  60. // History: 3-31-94 srikants Created
  61. //
  62. // Notes:
  63. //
  64. //----------------------------------------------------------------------------
  65. class CMMergeLogHdr
  66. {
  67. enum { sigHdr = 0x44484d4d }; // "MMHD" in ascii.
  68. public:
  69. void Init()
  70. {
  71. _sigHdr1 = _sigHdr2 = sigHdr;
  72. _cShadowIndex = _oSplitKey = 0;
  73. _widMaxIndex = _widMaxKeyList = widInvalid;
  74. }
  75. ULONG GetShadowIndexCount() const { return _cShadowIndex; }
  76. void SetShadowIndexCount( ULONG cShadowIndex )
  77. { _cShadowIndex = cShadowIndex; }
  78. ULONG GetSplitKeyOffset() const { return _oSplitKey; }
  79. void SetSplitKeyOffset( ULONG oSplitKey ) { _oSplitKey = oSplitKey; }
  80. BOOL IsValid() { return _sigHdr1 == sigHdr && _sigHdr2 == sigHdr ; }
  81. WORKID GetIndexWidMax() const { return _widMaxIndex; }
  82. void SetIndexWidMax( WORKID widMax ) { _widMaxIndex = widMax; }
  83. WORKID GetKeyListWidMax() const { return _widMaxKeyList; }
  84. void SetKeyListWidMax( WORKID widMax ) { _widMaxKeyList = widMax; }
  85. private:
  86. ULONG _sigHdr1; // Signature - must be sigHdr
  87. ULONG _cShadowIndex; // Number of shadow indexes in the merge.
  88. ULONG _oSplitKey; // Offset of the split key in the stream.
  89. ULONG _sigHdr2; // Signature - must be sigHdr
  90. ULONG _widMaxIndex; // Maximum workid in the new index.
  91. ULONG _widMaxKeyList; // Maximum workid in the key list.
  92. };
  93. DECL_DYNARRAY_INPLACE( CIndexIdArray, CIndexId );
  94. class CMMergeLog;
  95. //+---------------------------------------------------------------------------
  96. //
  97. // Class: CMMergeIndexList
  98. //
  99. // Purpose: Class for managing the list of indexes participating in a
  100. // master merge.
  101. //
  102. // History: 3-31-94 srikants Created
  103. //
  104. // Notes:
  105. //
  106. //----------------------------------------------------------------------------
  107. class CMMergeIndexList
  108. {
  109. enum { sigIdxList = 0x4c494d4d }; // "MMIL" in ascii.
  110. public:
  111. CMMergeIndexList( ULONG cShadowIndex = 64 );
  112. void Serialize( CRcovStrmWriteTrans & trans );
  113. void DeSerialize( CRcovStrmReadTrans & trans, PRcovStorageObj & obj );
  114. void AddIndex( CIndexId & iid );
  115. ULONG GetShadowIndexCount() const { return _cShadowIndex; }
  116. BOOL GetIndex( CIndexId & iid, ULONG nIdx );
  117. ULONG GetValidLength() const
  118. {
  119. return( OFFSET(CMMergeIndexList, _aShadowIndex) +
  120. _cShadowIndex * sizeof(CIndexId) );
  121. }
  122. private:
  123. ULONG _sigIdxList; // Must be sigIdxList.
  124. ULONG _cShadowIndex; // Count of the number of shadow indixes.
  125. CIndexIdArray _aShadowIndex; // Array of shadow indexes.
  126. };
  127. //+---------------------------------------------------------------------------
  128. //
  129. // Class: CMMergeSplitKey
  130. //
  131. // Purpose: Class for managing the "SplitKey" in the Master Log.
  132. //
  133. // History: 3-31-94 srikants Created
  134. //
  135. // Notes:
  136. //
  137. //----------------------------------------------------------------------------
  138. class CMMergeSplitKey
  139. {
  140. enum { sigSplitKey = 0x4b534d4d }; // "MMSK" in ascii.
  141. public:
  142. CMMergeSplitKey()
  143. {
  144. _sigSplitKey = sigSplitKey; _cbKey = 0; _pid = 0;
  145. _bitOffBegin.Init(0,0);
  146. _bitOffEnd.Init(0,0);
  147. }
  148. void GetKey( CKeyBuf & key );
  149. void GetOffset( BitOffset & bitOffBegin, BitOffset & bitOffEnd )
  150. {
  151. bitOffBegin = _bitOffBegin;
  152. bitOffEnd = _bitOffEnd;
  153. }
  154. void SetKey( const CKeyBuf & key );
  155. void SetOffset( const BitOffset & bitOffBegin,
  156. const BitOffset & bitOffEnd )
  157. {
  158. _bitOffBegin = bitOffBegin;
  159. _bitOffEnd = bitOffEnd;
  160. }
  161. ULONG GetCount() { return _cbKey; }
  162. BOOL IsValid() { return sigSplitKey == _sigSplitKey; }
  163. private:
  164. ULONG _sigSplitKey;
  165. ULONG _cbKey;
  166. BYTE _buf[MAXKEYSIZE];
  167. PROPID _pid;
  168. BitOffset _bitOffBegin;
  169. BitOffset _bitOffEnd;
  170. };
  171. inline void CMMergeSplitKey::GetKey( CKeyBuf & key )
  172. {
  173. key.SetCount( _cbKey );
  174. key.SetPid( _pid );
  175. ciAssert( _cbKey <= MAXKEYSIZE );
  176. memcpy( key.GetWritableBuf(), _buf, _cbKey );
  177. }
  178. inline void CMMergeSplitKey::SetKey( const CKeyBuf & key )
  179. {
  180. _pid = key.Pid();
  181. _cbKey = key.Count();
  182. ciAssert( _cbKey <= MAXKEYSIZE );
  183. memcpy( _buf, key.GetBuf(), _cbKey );
  184. }
  185. #include <poppack.h>
  186. //+---------------------------------------------------------------------------
  187. //
  188. // Class: CNewMMergeLog
  189. //
  190. // Purpose: Class used to create a new Master Log before starting a
  191. // master merge.
  192. //
  193. // History: 3-31-94 srikants Created
  194. //
  195. // Notes:
  196. //
  197. //----------------------------------------------------------------------------
  198. class CNewMMergeLog
  199. {
  200. public:
  201. CNewMMergeLog( PRcovStorageObj & obj );
  202. ~CNewMMergeLog();
  203. void AddPersistentIndex( CIndexId & iid )
  204. {
  205. _shadowIdxList.AddIndex( iid );
  206. }
  207. void SetKeyListWidMax( WORKID widMax ) { _widMaxKeyList = widMax; }
  208. void SetIndexWidMax( WORKID widMax ) { _widMaxIndex = widMax; }
  209. void Commit() { _fCommit = TRUE; }
  210. void DoCommit();
  211. private:
  212. BOOL _fCommit;
  213. PRcovStorageObj & _objMMLog;
  214. CRcovStrmWriteTrans _trans;
  215. CMMergeIndexList _shadowIdxList;
  216. WORKID _widMaxKeyList;
  217. WORKID _widMaxIndex;
  218. void SerializeIndexList();
  219. void AppendEmptySplitKeys();
  220. void WriteHeader();
  221. };
  222. //+---------------------------------------------------------------------------
  223. //
  224. // Class: CMMergeLog
  225. //
  226. // Purpose: The Master Merge Log class used during master merge to
  227. // manage serializing/de-serializing the split key.
  228. //
  229. // History: 3-31-94 srikants Created
  230. //
  231. // Notes:
  232. //
  233. //----------------------------------------------------------------------------
  234. const LONGLONG eSigMMergeLog = 0x474f4c4752454d4di64; // "MMERGLOG"
  235. class CMMergeLog
  236. {
  237. public:
  238. CMMergeLog( PRcovStorageObj & objMMLog );
  239. void GetIdxSplitKeyInfo( CKeyBuf & splitKey,
  240. BitOffset & bitOffBegin,
  241. BitOffset & bitOffEnd )
  242. {
  243. _idxSplitKey.GetKey( splitKey );
  244. _idxSplitKey.GetOffset( bitOffBegin, bitOffEnd );
  245. }
  246. WORKID GetIndexWidMax() const { return _widMaxIndex; }
  247. void SetIdxSplitKeyInfo( const CKeyBuf & splitKey,
  248. const BitOffset & bitOffBegin,
  249. const BitOffset & bitOffEnd )
  250. {
  251. _idxSplitKey.SetKey( splitKey );
  252. _idxSplitKey.SetOffset( bitOffBegin, bitOffEnd );
  253. ciDebugOut(( DEB_ITRACE, "Current split key is '%ws'\n",
  254. splitKey.GetStr() ));
  255. }
  256. void SetIndexWidMax( WORKID widMax ) { _widMaxIndex = widMax; }
  257. void GetKeyListSplitKeyInfo( CKeyBuf & splitKey,
  258. BitOffset & bitOffBegin,
  259. BitOffset & bitOffEnd
  260. )
  261. {
  262. _keylstSplitKey.GetKey(splitKey);
  263. _keylstSplitKey.GetOffset(bitOffBegin, bitOffEnd );
  264. }
  265. WORKID GetKeyListWidMax() const { return _widMaxKeyList; }
  266. void SetKeyListSplitKeyInfo( const CKeyBuf & splitKey,
  267. const BitOffset & bitOffBegin,
  268. const BitOffset & bitOffEnd
  269. )
  270. {
  271. _keylstSplitKey.SetKey( splitKey );
  272. _keylstSplitKey.SetOffset( bitOffBegin, bitOffEnd );
  273. }
  274. void SetKeyListWidMax( WORKID widMax ) { _widMaxKeyList = widMax; }
  275. void CheckPoint();
  276. #ifdef CIEXTMODE
  277. void CiExtDump(void *ciExtSelf);
  278. #endif
  279. private:
  280. const LONGLONG _sigMMergeLog;
  281. PRcovStorageObj & _objMMLog; // MasterMerge Log Object.
  282. CMMergeSplitKey _idxSplitKey;
  283. // The "SplitKey" between the current
  284. // master and the old master.
  285. CMMergeSplitKey _keylstSplitKey;
  286. // Split key for the key list.
  287. WORKID _widMaxIndex; // Maximum workid in the new index.
  288. WORKID _widMaxKeyList; // Maximum workid in the key list
  289. };
  290. //+---------------------------------------------------------------------------
  291. //
  292. // Class: CMMergeIdxListIter
  293. //
  294. // Purpose: Iterator to iterate through the list of participating
  295. // shadow indexes in the master merge.
  296. //
  297. // History: 3-31-94 srikants Created
  298. //
  299. // Notes:
  300. //
  301. //----------------------------------------------------------------------------
  302. class CMMergeIdxListIter
  303. {
  304. public:
  305. CMMergeIdxListIter( PRcovStorageObj & objMMLog );
  306. BOOL Found( CIndexId & iid );
  307. ULONG Count() { return _shadowIdxList.GetShadowIndexCount(); }
  308. BOOL AtEnd()
  309. {
  310. return _curr >= _shadowIdxList.GetShadowIndexCount();
  311. }
  312. void GetIndex( CIndexId & iid );
  313. void Advance() { _curr++; }
  314. void GetFirstIndex( CIndexId & iid )
  315. {
  316. _curr = 0;
  317. GetIndex( iid );
  318. }
  319. private:
  320. ULONG _curr; // The current index being returned.
  321. PRcovStorageObj & _objMMLog; // Recoverable storage object.
  322. CRcovStrmReadTrans _trans; // Read transaction.
  323. CMMergeIndexList _shadowIdxList;
  324. // The list of shadow indexes.
  325. };
  326. inline void CMMergeIdxListIter::GetIndex( CIndexId & iid )
  327. {
  328. Win4Assert( !AtEnd() );
  329. _shadowIdxList.GetIndex( iid, _curr );
  330. }