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.

496 lines
12 KiB

  1. #include "config.h"
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include "daedef.h"
  5. #include "ssib.h"
  6. #include "pib.h"
  7. #include "util.h"
  8. #include "page.h"
  9. #include "fucb.h"
  10. #include "stapi.h"
  11. #include "dirapi.h"
  12. #include "logapi.h"
  13. #include "log.h"
  14. #include "fileapi.h"
  15. #include "dbapi.h"
  16. DeclAssertFile; /* Declare file name for assert macros */
  17. /* variables used in redo only */
  18. BYTE *pbNext; // redo only - location of next buffer entry
  19. BYTE *pbRead; // redo only - location of next rec to flush
  20. INT isecRead; /* redo only - next disk to read. */
  21. BOOL fOnLastSec; /* redo only - on last sector of cur lg file */
  22. LGPOS lgposLastRec; /* mark for end of rec */
  23. VOID GetLgposOfPbNext(LGPOS *plgpos)
  24. {
  25. char *pb = PbSecAligned(pbNext);
  26. int ib = (int)(pbNext - pb);
  27. int isec;
  28. if (pb > pbRead)
  29. isec = (int)(pbRead + csecLGBuf * cbSec - pb) / cbSec;
  30. else
  31. isec = (int)(pbRead - pb) / cbSec;
  32. isec = isecRead - isec;
  33. plgpos->isec = (USHORT)isec;
  34. plgpos->ib = (USHORT)ib;
  35. plgpos->usGeneration = plgfilehdrGlobal->lgposLastMS.usGeneration;
  36. }
  37. #ifdef DEBUG
  38. /* calculate the lgpos of the LR */
  39. VOID PrintLgposReadLR ( VOID )
  40. {
  41. LGPOS lgpos;
  42. GetLgposOfPbNext(&lgpos);
  43. PrintF2("\n%2u,%3u,%3u",
  44. plgfilehdrGlobal->lgposLastMS.usGeneration,
  45. lgpos.isec, lgpos.ib);
  46. }
  47. #endif
  48. /*
  49. * Read first record pointed by plgposFirst.
  50. * Initialize isecRead, pbRead, and pbNext.
  51. */
  52. ERR ErrLGLocateFirstRedoLogRec(
  53. LGPOS *plgposPrevMS,
  54. LGPOS *plgposFirst, /* lgpos for first redo record */
  55. BYTE **ppbLR)
  56. {
  57. ERR err;
  58. char *pbNextT;
  59. /* read first sector, actually we read 2 pages such that we can
  60. * guarrantee that when calculate the length of the record, the
  61. * fixed part of the record is read in.
  62. */
  63. if (pbLGBufMin + 3 * cbSec > pbLGBufMax)
  64. return JET_errLogBufferTooSmall;
  65. if ( plgposPrevMS && plgposPrevMS->isec != 0 )
  66. {
  67. CallR(ErrLGRead(hfLog, plgposPrevMS->isec, pbLGBufMin, 1))
  68. CallS(ErrLGRead(hfLog, plgposPrevMS->isec + 1, pbLGBufMin + cbSec, 1));
  69. isecRead = plgposPrevMS->isec + 1; /* sector next to read. */
  70. pbRead = pbLGBufMin + cbSec;
  71. pbNext = pbLGBufMin + plgposPrevMS->ib;
  72. pbLastMSFlush = pbNext;
  73. lgposLastMSFlush = *plgposPrevMS;
  74. }
  75. else
  76. {
  77. CallR(ErrLGRead(hfLog, plgposFirst->isec, pbLGBufMin, 1))
  78. CallS(ErrLGRead(hfLog, plgposFirst->isec + 1, pbLGBufMin + cbSec, 1));
  79. isecRead = plgposFirst->isec + 1; /* sector next to read. */
  80. pbRead = pbLGBufMin + cbSec;
  81. pbNext = pbLGBufMin + plgposFirst->ib;
  82. /* initialize global variables */
  83. if ( lgposLastMSFlush.isec == plgposFirst->isec )
  84. {
  85. pbLastMSFlush = pbLGBufMin + lgposLastMSFlush.ib;
  86. }
  87. else
  88. {
  89. pbLastMSFlush = 0;
  90. memset( &lgposLastMSFlush, 0, sizeof(lgposLastMSFlush) );
  91. }
  92. }
  93. /* continue reading more sectors till next MS log record or
  94. * a Fill log record is reached.
  95. */
  96. pbNextT = pbNext;
  97. while (*(LRTYP*)pbNextT != lrtypFill)
  98. {
  99. char *pbAligned;
  100. /* goto next record */
  101. pbNextT += (ULONG) CbLGSizeOfRec((LR*)pbNextT);
  102. if (pbNextT > pbLGBufMax)
  103. return JET_errLogFileCorrupt;
  104. pbAligned = PbSecAligned(pbNextT);
  105. if (pbAligned >= pbRead)
  106. {
  107. int csecToRead;
  108. if ( plgposFirst->isec <= 2 &&
  109. plgfilehdrGlobal->lgposLastMS.ib == 0 &&
  110. plgfilehdrGlobal->lgposLastMS.isec <= 2 )
  111. {
  112. /* a special case where we tried to scan through this page and
  113. * realize that no MS or fill record is read. Should not read
  114. * beyond this page. Do not continue reading.
  115. */
  116. break;
  117. }
  118. /* physically read one more page to guarrantee that
  119. * the fix part of the log record is read in the
  120. * memory.
  121. */
  122. csecToRead = (int)(pbAligned - pbRead) / cbSec + 1;
  123. if (pbRead + csecToRead * cbSec > pbLGBufMax)
  124. return JET_errLogBufferTooSmall;
  125. CallR( ErrLGRead(hfLog, isecRead, pbRead, csecToRead ))
  126. isecRead += csecToRead;
  127. pbRead += csecToRead * cbSec;
  128. CallS( ErrLGRead(hfLog, isecRead, pbRead, 1 ));
  129. }
  130. /* reach next MS, break */
  131. if ( *(LRTYP*)pbNextT == lrtypMS )
  132. break;
  133. }
  134. if ( plgposPrevMS && plgposPrevMS->isec != 0 )
  135. {
  136. pbNext = pbLGBufMin + cbSec * ( plgposFirst->isec - plgposPrevMS->isec ); pbNext += plgposFirst->ib;
  137. }
  138. /* set up returned value. */
  139. *ppbLR = pbNext;
  140. return JET_errSuccess;
  141. }
  142. /*
  143. * Set pbNext to next available log record.
  144. */
  145. ERR ErrLGGetNextRec( BYTE **ppbLR )
  146. {
  147. ERR err;
  148. int cb;
  149. char *pb;
  150. LR *plr;
  151. LGPOS lgposT;
  152. BYTE *pbNextOld;
  153. /* caller should have taken care of the Fill case. */
  154. Assert (*(LRTYP *)pbNext != lrtypFill);
  155. /* move to next log record. */
  156. pbNextOld = pbNext;
  157. pbNext += (ULONG) CbLGSizeOfRec((LR*)pbNext);
  158. /* check if next log record is out of buffer range. */
  159. if (pbNext == pbRead)
  160. {
  161. /* the record ends on the sector boundary */
  162. pbNext = pbLGBufMin;
  163. pbRead = pbNext;
  164. /* read in one more page. */
  165. if (pbLGBufMin + cbSec > pbLGBufMax)
  166. return JET_errLogBufferTooSmall;
  167. CallR(ErrLGRead(hfLog, isecRead, pbLGBufMin, 1))
  168. isecRead += 1;
  169. pbRead = pbLGBufMin + cbSec;
  170. }
  171. if (pbNext > pbRead)
  172. {
  173. pbNext = pbNextOld;
  174. return errLGNoMoreRecords;
  175. }
  176. GetLgposOfPbNext(&lgposT);
  177. if ( CmpLgpos( &lgposT, &lgposLastRec ) > 0 )
  178. {
  179. pbNext = pbNextOld;
  180. return errLGNoMoreRecords;
  181. }
  182. plr = (LR *) pbNext;
  183. if (plr->lrtyp == lrtypFill)
  184. {
  185. /* end of current log file. */
  186. goto Done;
  187. }
  188. else if (plr->lrtyp == lrtypMS)
  189. {
  190. LRMS *plrms = (LRMS *)plr;
  191. #ifdef DEBUG
  192. // same as TraceRedo() in redo.c
  193. if (fDBGTraceRedo)
  194. {
  195. PrintLgposReadLR();
  196. ShowLR(plr);
  197. }
  198. #endif
  199. /* check if this MS was done completely by reading
  200. * the whole sector in. If it fails, then the sector
  201. * is the last sector available in the log file.
  202. */
  203. fOnLastSec = ( plrms->isecForwardLink == 0 ||
  204. ( lgposLastMSFlush.isec != 0 &&
  205. (
  206. plrms->isecBackLink != lgposLastMSFlush.isec ||
  207. plrms->ibBackLink != lgposLastMSFlush.ib
  208. ) ) );
  209. /* The MS were read in successfully, reset LastMSFlush
  210. * so that when switching from read mode to write mode,
  211. * we will have a correct LastMSFlush pointers.
  212. */
  213. pbLastMSFlush = (CHAR *) plrms;
  214. lgposLastMSFlush = lgposT;
  215. if ( !fOnLastSec )
  216. {
  217. if (isecRead <= plrms->isecForwardLink)
  218. {
  219. int csecToRead = plrms->isecForwardLink - isecRead + 1;
  220. Assert( csecToRead > 0 );
  221. pb = PbSecAligned(pbNext);
  222. cb = (int)(pbRead - pb);
  223. if (csecToRead + isecRead > csecLGBuf)
  224. {
  225. /* the multiple sector will not fit in rest of */
  226. /* the available buffer. Shift the buffer. */
  227. memmove(pbLGBufMin, pb, cb);
  228. pbRead = pbLGBufMin + cb; /* pbRead */
  229. pbNext = pbNext - pb + pbLGBufMin; /* pbNext */
  230. pbLastMSFlush = (CHAR *) plrms - pb + pbLGBufMin;
  231. }
  232. /* bring in multiple sectors */
  233. if (pbRead + csecToRead * cbSec > pbLGBufMax)
  234. {
  235. BYTE *pbLGBufMinT = pbLGBufMin;
  236. CallR( ErrLGInitLogBuffers( lLogBuffers ) );
  237. memcpy( pbLGBufMin, pbLGBufMinT, cb );
  238. pbRead = pbRead - pbLGBufMinT + pbLGBufMin;
  239. pbNext = pbNext - pbLGBufMinT + pbLGBufMin;
  240. pbLastMSFlush = pbLastMSFlush - pbLGBufMinT + pbLGBufMin;
  241. SysFree( pbLGBufMinT );
  242. }
  243. err = ErrLGRead(hfLog, isecRead, pbRead, csecToRead);
  244. if (err < 0)
  245. fOnLastSec = fTrue;
  246. else
  247. {
  248. /* Get pb of new lrms
  249. /*/
  250. CHAR *pbLrmsNew = pbRead + ( csecToRead - 1 ) * cbSec + ((LRMS *)pbLastMSFlush)->ibForwardLink;
  251. LRMS *plrmsNew = (LRMS *) pbLrmsNew;
  252. /* check if the check sum is correct
  253. /*/
  254. if ( plrmsNew->ulCheckSum != UlLGMSCheckSum( pbLrmsNew ) )
  255. fOnLastSec = fTrue;
  256. else
  257. {
  258. isecRead += csecToRead;
  259. pbRead += csecToRead * cbSec;
  260. }
  261. }
  262. }
  263. }
  264. /* skip MS and continue to read next record. */
  265. pbNextOld = pbNext;
  266. pbNext += CbLGSizeOfRec((LR*)pbNext);
  267. /* nomal end of generation */
  268. if ( fOnLastSec && plgfilehdrGlobal->fEndWithMS )
  269. return errLGNoMoreRecords;
  270. /* or abnormal end of log file */
  271. if ( fOnLastSec && PbSecAligned(pbNextOld) != PbSecAligned(pbNext))
  272. {
  273. pbNext = pbNextOld;
  274. return errLGNoMoreRecords;
  275. }
  276. }
  277. Done:
  278. *ppbLR = pbNext;
  279. return JET_errSuccess;
  280. }
  281. //+------------------------------------------------------------------------
  282. //
  283. // CbLGSizeOfRec
  284. // =======================================================================
  285. //
  286. // ERR CbLGSizeOfRec( plgrec )
  287. //
  288. // Returns the length of a log record.
  289. //
  290. // PARAMETER plgrec pointer to log record
  291. //
  292. // RETURNS size of log record in bytes
  293. //
  294. //-------------------------------------------------------------------------
  295. INT mplrtypcb[ lrtypMax ] = {
  296. /* 0 NOP */ sizeof( LRTYP ),
  297. /* 1 Start */ 0,
  298. /* 2 Quit */ 0,
  299. /* 3 MS */ sizeof( LRMS ),
  300. /* 4 Fill */ sizeof( LRTYP ),
  301. /* 5 Begin */ sizeof( LRBEGIN ),
  302. /* 6 Commit */ sizeof( LRCOMMIT ),
  303. /* 7 Abort */ sizeof( LRABORT ),
  304. /* 8 CreateDB */ 0,
  305. /* 9 AttachDB */ 0,
  306. /* 10 DetachDB */ 0,
  307. /* 11 InitFDP */ sizeof( LRINITFDPPAGE ),
  308. /* 12 Split */ 0,
  309. /* 13 EmptyPage*/ sizeof( LREMPTYPAGE ),
  310. /* 14 PageMerge*/ 0,
  311. /* 15 InsertND */ 0,
  312. /* 16 InsertIL */ 0,
  313. /* 17 Replace */ 0,
  314. /* 18 ReplaceC */ 0,
  315. /* 19 FDelete */ sizeof( LRFLAGDELETE ),
  316. /* 20 LockRec */ 0,
  317. /* 21 UpdtHdr */ sizeof( LRUPDATEHEADER ),
  318. /* 22 InsertI */ sizeof( LRINSERTITEM ),
  319. /* 23 InsertIS */ 0,
  320. /* 24 FDeleteI */ sizeof( LRFLAGITEM ),
  321. /* 25 FInsertI */ sizeof( LRFLAGITEM ),
  322. /* 26 DeleteI */ sizeof( LRDELETEITEM ),
  323. /* 27 SplitItm */ sizeof( LRSPLITITEMLISTNODE ),
  324. /* 28 Delta */ sizeof( LRDELTA ),
  325. /* 29 DelNode */ sizeof( LRDELETE ),
  326. /* 30 ELC */ sizeof( LRELC ),
  327. /* 31 FreeSpace*/ sizeof( LRFREESPACE ),
  328. /* 32 Undo */ sizeof( LRUNDO ),
  329. /* 33 RcvrUndo1*/ 0,
  330. /* 34 RcvrQuit1*/ 0,
  331. /* 35 RcvrUndo2*/ 0,
  332. /* 36 RcvrQuit2*/ 0,
  333. /* 37 FullBkUp */ 0,
  334. /* 38 IncBkUp */ 0,
  335. /* 39 CheckPage */ sizeof( LRCHECKPAGE ),
  336. };
  337. INT CbLGSizeOfRec( LR *plr )
  338. {
  339. INT cb;
  340. Assert( plr->lrtyp < lrtypMax );
  341. if ( ( cb = mplrtypcb[plr->lrtyp] ) != 0 )
  342. return cb;
  343. switch ( plr->lrtyp )
  344. {
  345. case lrtypStart:
  346. return sizeof(LRSTART);
  347. case lrtypQuit:
  348. case lrtypRecoveryQuit1:
  349. case lrtypRecoveryQuit2:
  350. return sizeof(LRQUITREC);
  351. case lrtypRecoveryUndo1:
  352. case lrtypRecoveryUndo2:
  353. case lrtypFullBackup:
  354. case lrtypIncBackup:
  355. {
  356. LRLOGRESTORE *plrlogrestore = (LRLOGRESTORE *) plr;
  357. return sizeof(LRLOGRESTORE) + plrlogrestore->cbPath;
  358. }
  359. case lrtypCreateDB:
  360. {
  361. LRCREATEDB *plrcreatedb = (LRCREATEDB *)plr;
  362. Assert( plrcreatedb->cb != 0 );
  363. return sizeof(LRCREATEDB) + plrcreatedb->cb;
  364. }
  365. case lrtypAttachDB:
  366. {
  367. LRATTACHDB *plrattachdb = (LRATTACHDB *)plr;
  368. Assert( plrattachdb->cb != 0 );
  369. return sizeof(LRATTACHDB) + plrattachdb->cb;
  370. }
  371. case lrtypDetachDB:
  372. {
  373. LRDETACHDB *plrdetachdb = (LRDETACHDB *)plr;
  374. Assert( plrdetachdb->cb != 0 );
  375. return sizeof( LRDETACHDB ) + plrdetachdb->cb;
  376. }
  377. case lrtypSplit:
  378. {
  379. LRSPLIT *plrsplit = (LRSPLIT *) plr;
  380. return sizeof( LRSPLIT ) + plrsplit->cbKey + plrsplit->cbKeyMac +
  381. sizeof( BKLNK ) * plrsplit->cbklnk;
  382. }
  383. case lrtypMerge:
  384. {
  385. LRMERGE *plrmerge = (LRMERGE *) plr;
  386. return sizeof( LRMERGE ) + sizeof( BKLNK ) * plrmerge->cbklnk;
  387. }
  388. case lrtypInsertNode:
  389. case lrtypInsertItemList:
  390. {
  391. LRINSERTNODE *plrinsertnode = (LRINSERTNODE *) plr;
  392. return sizeof(LRINSERTNODE) +
  393. plrinsertnode->cbKey + plrinsertnode->cbData;
  394. }
  395. case lrtypInsertItems:
  396. {
  397. LRINSERTITEMS *plrinsertitems = (LRINSERTITEMS *) plr;
  398. return sizeof(LRINSERTITEMS) +
  399. plrinsertitems->citem * sizeof(ITEM);
  400. }
  401. case lrtypReplace:
  402. case lrtypReplaceC:
  403. {
  404. LRREPLACE *plrreplace = (LRREPLACE *) plr;
  405. return sizeof(LRREPLACE) + plrreplace->cb +
  406. ( plrreplace->fOld ? plrreplace->cbOldData : 0 );
  407. }
  408. case lrtypLockRec:
  409. {
  410. LRLOCKREC *plrlockrec = (LRLOCKREC *) plr;
  411. return sizeof(LRLOCKREC) + plrlockrec->cbOldData;
  412. }
  413. default:
  414. Assert( fFalse );
  415. }
  416. return 0;
  417. }