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.

671 lines
20 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: RCSTRMIT.HXX
  7. //
  8. // Contents: Persistent Recoverable Stream Iterators for fixed
  9. // size records.
  10. //
  11. // Classes: CRcovStrmReadIter
  12. // CRcovStrmWriteIter
  13. // CRcovStrmAppendIter
  14. //
  15. // History: 25-Jan-94 SrikantS Created.
  16. //
  17. //----------------------------------------------------------------------------
  18. #pragma once
  19. #include <rcstxact.hxx>
  20. //+---------------------------------------------------------------------------
  21. //
  22. // Class: CRcovStrmIter
  23. //
  24. // Purpose: Iterator for the recoverable stream class assuming fixed
  25. // size records are stored in the stream.
  26. //
  27. // History: 1-25-94 srikants Created
  28. //
  29. //----------------------------------------------------------------------------
  30. class CRcovStrmIter
  31. {
  32. public:
  33. inline CRcovStrmIter( CRcovStrmTrans & trans , USHORT cbRec );
  34. inline BOOL GetRec( void *pvRec, ULONG iRec );
  35. inline void GetRec( void *pvRec );
  36. inline ULONG GetVariableRecSize();
  37. inline void GetVariableRecData( void * pvRec, ULONG cbRec );
  38. BOOL AtEnd() const { return _trans.AtEnd(); }
  39. inline void Advance();
  40. inline void Seek( ULONG iRec );
  41. ULONG UserDataSize( ULONG cRec ) { return cRec * (_cbRec + _CHECKSUM_SIZE); }
  42. ULONG UserRecordCount( ULONG cbUserData ) { return cbUserData / (_cbRec + _CHECKSUM_SIZE); }
  43. static unsigned SizeofChecksum() { return _CHECKSUM_SIZE; }
  44. protected:
  45. enum { _CHECKSUM_SIZE = sizeof(ULONG) };
  46. inline ULONG CheckSum( void const * pvRec ) const;
  47. inline ULONG CheckSum( void const * pvRec, unsigned cbRec ) const;
  48. CRcovStrmTrans & _trans; // Transaction context
  49. const USHORT _cbRec; // Size of user record, sans checksum
  50. };
  51. //+---------------------------------------------------------------------------
  52. //
  53. // Method: CRcovStrmIter::CRcovStrmIter, public
  54. //
  55. // Synopsis: Constructor. Just squirrels away member variables.
  56. //
  57. // Arguments: [trans] -- Transaction context to iterate
  58. // [cbRec] -- Size of 'records' to be written.
  59. //
  60. // History: 27-May-1998 KyleP Added header
  61. //
  62. //----------------------------------------------------------------------------
  63. inline CRcovStrmIter::CRcovStrmIter( CRcovStrmTrans & trans , USHORT cbRec )
  64. : _trans( trans ),
  65. _cbRec(cbRec)
  66. {
  67. }
  68. //+---------------------------------------------------------------------------
  69. //
  70. // Method: CRcovStrmIter::Advance, public
  71. //
  72. // Synopsis: Moves to next record
  73. //
  74. // History: 27-May-1998 KyleP Added header
  75. //
  76. //----------------------------------------------------------------------------
  77. inline void CRcovStrmIter::Advance()
  78. {
  79. Win4Assert( !AtEnd() );
  80. _trans.Advance( _cbRec + _CHECKSUM_SIZE );
  81. }
  82. //+---------------------------------------------------------------------------
  83. //
  84. // Method: CRcovStrmIter::Seek, public
  85. //
  86. // Synopsis: Moves to specified record
  87. //
  88. // Arguments: [iRec] -- Record to position to.
  89. //
  90. // History: 27-May-1998 KyleP Created
  91. //
  92. //----------------------------------------------------------------------------
  93. inline void CRcovStrmIter::Seek( ULONG iRec )
  94. {
  95. _trans.Seek( iRec * (_cbRec + _CHECKSUM_SIZE) );
  96. }
  97. //+---------------------------------------------------------------------------
  98. //
  99. // Method: CRcovStrmIter::CheckSum, protected
  100. //
  101. // Synopsis: Computes checksum for record
  102. //
  103. // Arguments: [pvRec] -- Record to examine
  104. //
  105. // Returns: Checksum
  106. //
  107. // History: 27-May-1998 KyleP Created
  108. //
  109. // Notes: Checksum is never 0. This is to avoid a common failed write
  110. // scenario where zeros are written (or nothing is ever written)
  111. // to a persistent data structure.
  112. //
  113. //----------------------------------------------------------------------------
  114. inline ULONG CRcovStrmIter::CheckSum( void const * pvRec ) const
  115. {
  116. return CheckSum( pvRec, _cbRec );
  117. }
  118. //+---------------------------------------------------------------------------
  119. //
  120. // Method: CRcovStrmIter::CheckSum, protected
  121. //
  122. // Synopsis: Computes checksum for variable size records
  123. //
  124. // Arguments: [pvRec] -- Record to examine
  125. // [cbRec] -- Size of record
  126. //
  127. // Returns: Checksum
  128. //
  129. // History: 1-Jun-1998 VikasMan Created
  130. //
  131. // Notes: Checksum is never 0. This is to avoid a common failed write
  132. // scenario where zeros are written (or nothing is ever written)
  133. // to a persistent data structure.
  134. //
  135. //----------------------------------------------------------------------------
  136. inline ULONG CRcovStrmIter::CheckSum( void const * pvRec, unsigned cbRec ) const
  137. {
  138. BYTE * pb = (BYTE *)pvRec;
  139. ULONG ulCheckSum = 0;
  140. //
  141. // First, the DWORD granular portion
  142. //
  143. unsigned cbEnd = cbRec - _CHECKSUM_SIZE;
  144. for ( unsigned i = 0; i <= cbEnd; i += _CHECKSUM_SIZE )
  145. {
  146. ulCheckSum += *(ULONG UNALIGNED *)pb;
  147. pb += _CHECKSUM_SIZE;
  148. }
  149. //
  150. // Then whatever is left.
  151. //
  152. ULONG ul = 0;
  153. for ( ; i < cbRec; i++ )
  154. {
  155. ul = (ul << 8) + *pb;
  156. pb++;
  157. }
  158. ulCheckSum += ul;
  159. //
  160. // Make sure the checksum is never zero. Just to avoid an obvious case
  161. // of error where a whole section has been zero-ed (including checksum).
  162. //
  163. if ( 0 == ulCheckSum )
  164. ulCheckSum = 1;
  165. return ulCheckSum;
  166. }
  167. //+---------------------------------------------------------------------------
  168. //
  169. // Function: CRcovStrmIter::GetRec, public
  170. //
  171. // Synopsis: Gets the specified record.
  172. //
  173. // Effects: Positions the current pointer after the current read.
  174. //
  175. // Arguments: [pvRec] -- Buffer to read the contents into.
  176. // [iRec] -- Number of the record, starting at 0.
  177. //
  178. // Returns: TRUE if a record was successfully read. FALSE if iRec
  179. // is beyond the end of stream.
  180. //
  181. // History: 2-10-94 srikants Created
  182. //
  183. //----------------------------------------------------------------------------
  184. inline BOOL CRcovStrmIter::GetRec( void * pvRec , ULONG iRec )
  185. {
  186. if ( !_trans.Seek(iRec * (_cbRec + _CHECKSUM_SIZE) ) || AtEnd() ) {
  187. return FALSE;
  188. }
  189. ULONG cbRead = _trans.Read( pvRec, _cbRec );
  190. Win4Assert( cbRead == _cbRec );
  191. ULONG ulCheckSum;
  192. if ( _CHECKSUM_SIZE != _trans.Read( &ulCheckSum, sizeof(ulCheckSum) ) )
  193. {
  194. ciDebugOut(( DEB_ERROR, "Error reading checksum for record %u (cbRec = %u).\n",
  195. iRec, _cbRec ));
  196. Win4Assert( !"Bad checksum" );
  197. THROW( CException(CI_CORRUPT_CATALOG) );
  198. }
  199. if ( ulCheckSum != CheckSum( pvRec ) )
  200. {
  201. ciDebugOut(( DEB_ERROR,
  202. "Incorrect checksum 0x%x (should be 0x%x) for record %u (cbRec = %u). pvRec = 0x%x\n",
  203. CheckSum( pvRec ), ulCheckSum, iRec, _cbRec, pvRec ));
  204. Win4Assert( !"Bad checksum" );
  205. THROW( CException(CI_CORRUPT_CATALOG) );
  206. }
  207. return cbRead == _cbRec;
  208. }
  209. //+---------------------------------------------------------------------------
  210. //
  211. // Function: CRcovStrmIter::GetRec, public
  212. //
  213. // Synopsis: Gets the current record.
  214. //
  215. // Effects: Positions the current pointer after the current read.
  216. //
  217. // Arguments: [pvRec] -- Buffer to read the contents into.
  218. //
  219. // History: 27-May-1998 KyleP Created
  220. //
  221. //----------------------------------------------------------------------------
  222. inline void CRcovStrmIter::GetRec( void *pvRec )
  223. {
  224. GetVariableRecData( pvRec, _cbRec );
  225. }
  226. //+---------------------------------------------------------------------------
  227. //
  228. // Function: CRcovStrmIter::GetVariableRecSize, public
  229. //
  230. // Synopsis: Gets the size of the current variable record.
  231. //
  232. // Effects: Positions the current pointer after the current read.
  233. //
  234. // Arguments:
  235. //
  236. // Returns: The size in bytes of the records
  237. //
  238. // History: 1-Jun-1998 VikasMan Created
  239. //
  240. //----------------------------------------------------------------------------
  241. inline ULONG CRcovStrmIter::GetVariableRecSize()
  242. {
  243. Win4Assert( !AtEnd() );
  244. ULONG cbRec;
  245. ULONG cbRead;
  246. // Read Size
  247. cbRead = _trans.Read( &cbRec, sizeof( cbRec ) );
  248. Win4Assert( sizeof( cbRec ) == cbRead );
  249. Win4Assert( cbRec );
  250. return cbRec;
  251. }
  252. //+---------------------------------------------------------------------------
  253. //
  254. // Function: CRcovStrmIter::GetVariableRecData, public
  255. //
  256. // Synopsis: Gets the current variable record.
  257. //
  258. // Effects: Positions the current pointer after the current read.
  259. //
  260. // Arguments: [pvRec] -- Pointer to buffer to read the contents into.
  261. // [cbRec] -- Size in bytes of pvRec
  262. //
  263. //
  264. // History: 1-Jun-1998 VikasMan Created
  265. //
  266. //----------------------------------------------------------------------------
  267. inline void CRcovStrmIter::GetVariableRecData( void * pvRec, ULONG cbRec )
  268. {
  269. Win4Assert( !AtEnd() );
  270. ULONG cbRead = _trans.Read( pvRec, cbRec );
  271. Win4Assert( cbRead == cbRec );
  272. ULONG ulCheckSum;
  273. if ( _CHECKSUM_SIZE != _trans.Read( &ulCheckSum, sizeof(ulCheckSum) ) )
  274. {
  275. ciDebugOut(( DEB_ERROR, "Error reading checksum.\n" ));
  276. Win4Assert( !"Bad checksum" );
  277. THROW( CException(CI_CORRUPT_CATALOG) );
  278. }
  279. if ( ulCheckSum != CheckSum( pvRec, cbRec ) )
  280. {
  281. ciDebugOut(( DEB_ERROR,
  282. "Incorrect checksum 0x%x (should be 0x%x). pvRec = 0x%x\n",
  283. CheckSum( pvRec ), ulCheckSum, pvRec ));
  284. Win4Assert( !"Bad checksum" );
  285. THROW( CException(CI_CORRUPT_CATALOG) );
  286. }
  287. }
  288. #if 0 // untested unsused new function
  289. //+---------------------------------------------------------------------------
  290. //
  291. // Function: CRcovStrmIter::GetVariableRec, public
  292. //
  293. // Synopsis: Gets the current variable record. In the process would also
  294. // allocate memory for it
  295. //
  296. // Effects: Positions the current pointer after the current read.
  297. //
  298. // Arguments: [ppvRec] -- Pointer to buffer to read the contents into.
  299. //
  300. // Returns: The size in bytes of *ppvRec
  301. //
  302. // History: 1-Jun-1998 VikasMan Created
  303. //
  304. //----------------------------------------------------------------------------
  305. inline ULONG CRcovStrmIter::GetVariableRec( void ** ppvRec )
  306. {
  307. Win4Assert( !AtEnd() );
  308. *ppvRec = NULL;
  309. ULONG cbRec;
  310. // Read Size
  311. cbRec = GetVariableRecSize();
  312. // Now allocate and read data
  313. *ppvRec = (void*) new BYTE[cbRec];
  314. XPtrST<BYTE> xRec((BYTE*)*ppvRec);
  315. GetVariableRecData( *ppvRec, cbRec );
  316. xRec.Acquire();
  317. return cbRec;
  318. }
  319. #endif
  320. //+---------------------------------------------------------------------------
  321. //
  322. // Class: CRcovStrmReadIter
  323. //
  324. // Purpose: Read-only version of recoverable stream iterator.
  325. //
  326. // History: 1-25-94 srikants Created
  327. //
  328. //----------------------------------------------------------------------------
  329. class CRcovStrmReadIter : public CRcovStrmIter
  330. {
  331. public:
  332. inline CRcovStrmReadIter( CRcovStrmReadTrans &readTrans, USHORT cbRec );
  333. };
  334. //+---------------------------------------------------------------------------
  335. //
  336. // Method: CRcovStrmReadIter::CRcovStrmReadIter, public
  337. //
  338. // Synopsis: Constructor. Just squirrels away member variables.
  339. //
  340. // Arguments: [trans] -- Transaction context to iterate
  341. // [cbRec] -- Size of 'records' to be written.
  342. //
  343. // History: 27-May-1998 KyleP Added header
  344. //
  345. //----------------------------------------------------------------------------
  346. inline CRcovStrmReadIter::CRcovStrmReadIter( CRcovStrmReadTrans & readTrans , USHORT cbRec )
  347. : CRcovStrmIter( readTrans, cbRec )
  348. {
  349. _trans.Seek(0);
  350. }
  351. //+---------------------------------------------------------------------------
  352. //
  353. // Class: CRcovStrmAppendIter
  354. //
  355. // Purpose: Iterator to append fixed size records to the recoverable
  356. // streams. This is just an optimized case of a write iterator.
  357. //
  358. // History: 2-10-94 srikants Created
  359. //
  360. //----------------------------------------------------------------------------
  361. class CRcovStrmAppendIter : public CRcovStrmIter
  362. {
  363. public:
  364. inline CRcovStrmAppendIter( CRcovStrmAppendTrans &appendTrans, USHORT cbRec );
  365. inline void AppendRec( const void *pvRec );
  366. inline void AppendVariableRec( const void *pvRec, ULONG cbRec );
  367. private:
  368. CRcovStrmAppendTrans & _appendTrans;
  369. };
  370. //+---------------------------------------------------------------------------
  371. //
  372. // Method: CRcovStrmAppendIter::CRcovStrmAppendIter, public
  373. //
  374. // Synopsis: Constructor. Just squirrels away member variables.
  375. //
  376. // Arguments: [trans] -- Transaction context to iterate
  377. // [cbRec] -- Size of 'records' to be written.
  378. //
  379. // History: 27-May-1998 KyleP Added header
  380. //
  381. //----------------------------------------------------------------------------
  382. inline CRcovStrmAppendIter::CRcovStrmAppendIter( CRcovStrmAppendTrans & trans, USHORT cbRec )
  383. : CRcovStrmIter( trans, cbRec ),
  384. _appendTrans( trans )
  385. {
  386. _appendTrans.Seek( ENDOFSTRM );
  387. }
  388. //+---------------------------------------------------------------------------
  389. //
  390. // Method: CRcovStrmAppendIter::AppendRec, public
  391. //
  392. // Synopsis: Appends record to end of stream.
  393. //
  394. // Arguments: [pvRec] -- Record to append.
  395. //
  396. // History: 27-May-1998 KyleP Added header
  397. //
  398. //----------------------------------------------------------------------------
  399. inline void CRcovStrmAppendIter::AppendRec( const void *pvRec )
  400. {
  401. _appendTrans.Append( pvRec, _cbRec );
  402. ULONG ulCheckSum = CheckSum( pvRec );
  403. _appendTrans.Append( &ulCheckSum, sizeof(ulCheckSum), FALSE );
  404. }
  405. //+---------------------------------------------------------------------------
  406. //
  407. // Method: CRcovStrmAppendIter::AppendVariableRec, public
  408. //
  409. // Synopsis: Appends variable size record to end of stream
  410. //
  411. // Arguments: [pvRec] -- Record to append.
  412. // [cbRec] -- Count in bytes of pvRec
  413. //
  414. // Returns: void
  415. //
  416. // History: 01-Jun-1998 VikasMan Created
  417. //
  418. //----------------------------------------------------------------------------
  419. inline void CRcovStrmAppendIter::AppendVariableRec( const void *pvRec,
  420. ULONG cbRec )
  421. {
  422. ULONG ulCheckSum;
  423. Win4Assert( cbRec != 0 && pvRec != 0 );
  424. // first write the size
  425. _appendTrans.Append( &cbRec, sizeof( cbRec ), FALSE );
  426. // next write the data
  427. _appendTrans.Append( pvRec, cbRec );
  428. ulCheckSum = CheckSum( pvRec, cbRec );
  429. _appendTrans.Append( &ulCheckSum, sizeof(ulCheckSum), FALSE );
  430. }
  431. //+---------------------------------------------------------------------------
  432. //
  433. // Class: CRcovStrmWriteIter
  434. //
  435. // Purpose: Iterator for writing fixed size anywhere in the
  436. // recoverable stream.
  437. //
  438. // History: 2-10-94 srikants Created
  439. //
  440. //----------------------------------------------------------------------------
  441. class CRcovStrmWriteIter : public CRcovStrmIter
  442. {
  443. public:
  444. inline CRcovStrmWriteIter( CRcovStrmWriteTrans & writeTrans, USHORT cbRec );
  445. inline BOOL SetRec( const void *pvBuf, ULONG iRec );
  446. inline void SetRec( const void *pvBuf );
  447. inline void AppendRec( const void *pvBuf );
  448. #if 0 // untested unused new function
  449. inline void SetVariableRec( const void *pvRec,
  450. ULONG cbRec,
  451. BOOL fAppend = FALSE );
  452. #endif
  453. private:
  454. CRcovStrmWriteTrans & _writeTrans;
  455. };
  456. //+---------------------------------------------------------------------------
  457. //
  458. // Method: CRcovStrmWriteIter::CRcovStrmWriteIter, public
  459. //
  460. // Synopsis: Constructor. Just squirrels away member variables.
  461. //
  462. // Arguments: [trans] -- Transaction context to iterate
  463. // [cbRec] -- Size of 'records' to be written.
  464. //
  465. // History: 27-May-1998 KyleP Added header
  466. //
  467. //----------------------------------------------------------------------------
  468. inline CRcovStrmWriteIter::CRcovStrmWriteIter( CRcovStrmWriteTrans & writeTrans, USHORT cbRec )
  469. : CRcovStrmIter( writeTrans, cbRec ),
  470. _writeTrans(writeTrans)
  471. {
  472. }
  473. //+---------------------------------------------------------------------------
  474. //
  475. // Method: CRcovStrmWriteIter::SetRec, public
  476. //
  477. // Synopsis: Writes specified record to stream.
  478. //
  479. // Arguments: [pvRec] -- Record data
  480. // [iRec] -- Location at which write should occur
  481. //
  482. // History: 27-May-1998 KyleP Added header
  483. //
  484. //----------------------------------------------------------------------------
  485. inline BOOL CRcovStrmWriteIter::SetRec( const void * pvRec, ULONG iRec )
  486. {
  487. if (! _writeTrans.Seek( (_cbRec + _CHECKSUM_SIZE) * iRec ) || AtEnd() )
  488. {
  489. return FALSE;
  490. }
  491. SetRec( pvRec );
  492. return TRUE;
  493. }
  494. //+---------------------------------------------------------------------------
  495. //
  496. // Method: CRcovStrmWriteIter::SetRec, public
  497. //
  498. // Synopsis: Writes specified record to current location in stream.
  499. //
  500. // Arguments: [pvRec] -- Record data
  501. //
  502. // History: 27-May-1998 KyleP Added header
  503. //
  504. //----------------------------------------------------------------------------
  505. inline void CRcovStrmWriteIter::SetRec( const void * pvRec )
  506. {
  507. _writeTrans.Write( pvRec, _cbRec );
  508. ULONG ulCheckSum = CheckSum( pvRec );
  509. _writeTrans.Write( &ulCheckSum, sizeof(ulCheckSum) );
  510. }
  511. //+---------------------------------------------------------------------------
  512. //
  513. // Method: CRcovStrmWriteIter::AppendRec, public
  514. //
  515. // Synopsis: Appends record to end of stream.
  516. //
  517. // Arguments: [pvRec] -- Record to append.
  518. //
  519. // History: 27-May-1998 KyleP Added header
  520. //
  521. //----------------------------------------------------------------------------
  522. inline void CRcovStrmWriteIter::AppendRec( const void *pvRec )
  523. {
  524. _writeTrans.Append( pvRec, _cbRec );
  525. ULONG ulCheckSum = CheckSum( pvRec );
  526. _writeTrans.Write( &ulCheckSum, sizeof(ulCheckSum) );
  527. }
  528. #if 0 // untested unused new function
  529. //+---------------------------------------------------------------------------
  530. //
  531. // Method: CRcovStrmWriteIter::SetVariableRec, public
  532. //
  533. // Synopsis: Writes/Appends variable size record to end of stream
  534. //
  535. // Arguments: [pvRec] -- Record to append.
  536. // [cbRec] -- Count in bytes of pvRec
  537. // [fAppend] -- If TRUE, then record is appended
  538. //
  539. // Returns: void
  540. //
  541. // History: 01-Jun-1998 VikasMan Created
  542. //
  543. //----------------------------------------------------------------------------
  544. inline void CRcovStrmWriteIter::SetVariableRec( const void *pvRec,
  545. ULONG cbRec,
  546. BOOL fAppend /* = FALSE */ )
  547. {
  548. ULONG ulCheckSum;
  549. Win4Assert( cbRec != 0 && pvRec != 0 );
  550. // first write the size
  551. if ( fAppend )
  552. _writeTrans.Append( &cbRec, sizeof( cbRec ) );
  553. else
  554. _writeTrans.Write( &cbRec, sizeof( cbRec ) );
  555. // next write the data
  556. _writeTrans.Write( pvRec, cbRec );
  557. ulCheckSum = CheckSum( pvRec, cbRec );
  558. _writeTrans.Write( &ulCheckSum, sizeof(ulCheckSum) );
  559. }
  560. #endif