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.

777 lines
20 KiB

  1. #ifndef _STAPI_H
  2. #define _STAPI_H
  3. // Redirect Asserts in inline code to seem to fire from this file
  4. #define szAssertFilename __FILE__
  5. //---- externs -------------------------------------------------------------
  6. extern CRIT critBuf;
  7. extern TRX trxOldest;
  8. extern TRX trxNewest;
  9. extern CRIT critCommit0;
  10. extern SIG sigBFCleanProc;
  11. //---- IO (io.c) ----------------------------------------------------------
  12. ERR ErrIOInit( VOID );
  13. ERR ErrIOTerm( BOOL fNormal );
  14. /* Reserve first 2 pages of a database.
  15. */
  16. #define cpageDBReserved 2
  17. STATIC INLINE LONG LOffsetOfPgnoLow( PGNO pgno ) { return ( pgno -1 + cpageDBReserved ) << 12; }
  18. STATIC INLINE LONG LOffsetOfPgnoHigh( PGNO pgno ) { return ( pgno -1 + cpageDBReserved ) >> 20; }
  19. VOID IOCloseFile( HANDLE hf );
  20. ERR ErrIONewSize( DBID dbid, CPG cpg );
  21. BOOL FIOFileExists( CHAR *szFileName );
  22. ERR ErrIOLockDbidByNameSz( CHAR *szFileName, DBID *pdbid );
  23. ERR ErrIOLockDbidByDbid( DBID dbid );
  24. ERR ErrIOLockNewDbid( DBID *pdbid, CHAR *szDatabaseName );
  25. ERR ErrIOSetDbid( DBID dbid, CHAR *szDatabaseName );
  26. VOID IOFreeDbid( DBID dbid );
  27. void BFOldestLgpos( LGPOS *plgposCheckPoint );
  28. VOID BFPurge( DBID dbid );
  29. STATIC INLINE BOOL FIODatabaseOpen ( DBID dbid )
  30. {
  31. AssertCriticalSection( critJet );
  32. return rgfmp[dbid].hf != handleNil;
  33. }
  34. ERR ErrIOOpenDatabase( DBID dbid, CHAR *szDatabaseName, CPG cpg );
  35. VOID IOCloseDatabase( DBID dbid );
  36. ERR ErrIODeleteDatabase( DBID dbid );
  37. BOOL FIODatabaseInUse( DBID dbid );
  38. BOOL FIODatabaseAvailable( DBID dbid );
  39. STATIC INLINE VOID IOUnlockDbid( DBID dbid )
  40. {
  41. SgEnterCriticalSection( critBuf );
  42. Assert( FDBIDWait( dbid ) );
  43. DBIDResetWait( dbid );
  44. SgLeaveCriticalSection( critBuf );
  45. }
  46. STATIC INLINE BOOL FIOExclusiveByAnotherSession( DBID dbid, PIB *ppib )
  47. {
  48. Assert( FDBIDWait( dbid ) );
  49. return FDBIDExclusiveByAnotherSession( dbid, ppib );
  50. }
  51. STATIC INLINE VOID IOSetExclusive( DBID dbid, PIB *ppib )
  52. {
  53. Assert( FDBIDWait( dbid ) );
  54. Assert( !( FDBIDExclusive( dbid ) ) );
  55. DBIDSetExclusive( dbid, ppib );
  56. }
  57. STATIC INLINE VOID IOResetExclusive( DBID dbid )
  58. {
  59. Assert( FDBIDWait( dbid ) );
  60. DBIDResetExclusive( dbid );
  61. }
  62. STATIC INLINE BOOL FIOReadOnly( DBID dbid )
  63. {
  64. Assert( FDBIDWait( dbid ) );
  65. return FDBIDReadOnly( dbid );
  66. }
  67. STATIC INLINE VOID IOSetReadOnly( DBID dbid )
  68. {
  69. Assert( FDBIDWait( dbid ) );
  70. DBIDSetReadOnly( dbid );
  71. }
  72. STATIC INLINE VOID IOResetReadOnly( DBID dbid )
  73. {
  74. Assert( FDBIDWait( dbid ) );
  75. DBIDResetReadOnly( dbid );
  76. }
  77. STATIC INLINE BOOL FIOAttached( DBID dbid )
  78. {
  79. Assert( FDBIDWait( dbid ) );
  80. return FDBIDAttached( dbid );
  81. }
  82. STATIC INLINE VOID IOSetAttached( DBID dbid )
  83. {
  84. Assert( FDBIDWait( dbid ) );
  85. Assert( !( FDBIDAttached( dbid ) ) );
  86. DBIDSetAttached( dbid );
  87. }
  88. STATIC INLINE VOID IOResetAttached( DBID dbid )
  89. {
  90. Assert( FDBIDWait( dbid ) );
  91. Assert( FDBIDAttached( dbid ) );
  92. DBIDResetAttached( dbid );
  93. }
  94. //---- BUF (buf.c) ----------------------------------------------------------
  95. typedef struct _lru // LRU List
  96. {
  97. LONG cbfAvail; // clean available buffers in LRU list
  98. struct _bf *pbfLRU; // Least Recently Used buffer
  99. struct _bf *pbfMRU; // Most Recently Used buffer
  100. } LRULIST;
  101. typedef struct _bgcb // Buffer Group Control Block
  102. {
  103. struct _bgcb *pbgcbNext; // pointer to the next BCGB
  104. struct _bf *rgbf; // buffer control blocks for group
  105. struct _page *rgpage; // buffer control blocks for group
  106. LONG cbfGroup; // number of bfs in this group
  107. LONG cbfThresholdLow; // threshold to start cleaning buffers
  108. LONG cbfThresholdHigh; // threshold to stop cleaning buffers
  109. LRULIST lrulist;
  110. } BGCB;
  111. #define pbgcbNil ((BGCB*)0)
  112. #define PbgcbMEMAlloc() (BGCB*)PbMEMAlloc(iresBGCB)
  113. #ifdef DEBUG /* Debug check for illegal use of freed bgcb */
  114. #define MEMReleasePbgcb(pbgcb) { MEMRelease(iresBGCB, (BYTE*)(pbgcb)); pbgcb = pbgcbNil; }
  115. #else
  116. #define MEMReleasePbgcb(pbgcb) { MEMRelease(iresBGCB, (BYTE*)(pbgcb)); }
  117. #endif
  118. #define BUT INT
  119. #define butBuffer 0
  120. #define butHistory 1
  121. #define ibfNotUsed -1
  122. typedef struct _he
  123. {
  124. BUT but:2; // must use 2 bits to avoid sign extension when converting to int
  125. INT ibfHashNext:30; // hash table overflow
  126. } HE;
  127. typedef struct _hist
  128. {
  129. ULONG ulBFTime;
  130. PN pn;
  131. INT ipbfHISTHeap;
  132. } HIST;
  133. typedef struct _bf
  134. {
  135. struct _page *ppage; // pointer to page buffer
  136. #if defined( _X86_ ) && defined( X86_USE_SEM )
  137. LONG volatile lLock; // num of locks being asked
  138. LONG cSemWait; // num of user waiting for on semaphore
  139. SEM sem;
  140. #endif // defined( _X86_ ) && defined( X86_USE_SEM )
  141. PN pn; // physical pn of cached page
  142. ULONG fDirty:1; // indicates page needs to be flushed
  143. // the following flags are mutual exclusive:
  144. ULONG fDirectRead:1; // buffer is being direct read
  145. ULONG fAsyncRead:1; // buffer is being async read
  146. ULONG fSyncRead:1; // buffer is being sync read
  147. ULONG fAsyncWrite:1; // buffer is being async written
  148. ULONG fSyncWrite:1; // buffer is being sync written
  149. ULONG fHold:1; // buffer is in transient state
  150. ULONG fIOError:1; // indicates read/write error
  151. #ifdef DEBUG
  152. ULONG fInHash:1; // BF is currently in hash table
  153. #endif // DEBUG
  154. ULONG fInLRUK:1; // BF is in LRUK heap or LRUK list
  155. ULONG fVeryOld:1; // BF is very old relative to last check point
  156. ULONG fPatch:1; // BF is being written to the patch file
  157. ULONG fNeedPatch:1; // BF need to write patch file after regular write.
  158. LONG ipbfHeap; // index in heap
  159. LONG cWriteLatch; // if cWriteLatch > 0, page cannot be updated by other
  160. LONG cWaitLatch;
  161. LONG cPin; // if cPin > 0 then buf cannot be overlayed
  162. #ifdef READ_LATCH
  163. LONG cReadLatch; // if cReadLatch > 0, page cannot be updated
  164. #endif // READ_LATCH
  165. PIB *ppibWriteLatch; // thread with write latch
  166. PIB *ppibWaitLatch; // thread with wait latch
  167. struct _bf *pbfLRU; // pointer to less recently used buffer
  168. struct _bf *pbfMRU; // pointer to more recently used buffer
  169. TRX trxLastRef; // last transaction that referenced us
  170. ULONG ulBFTime1; // last reference time
  171. ULONG ulBFTime2; // previous to last reference time
  172. struct _bf *pbfNextBatchIO; // next BF in BatchIO list
  173. LONG ipageBatchIO;
  174. ERR err; // error code for err occurs during the IO
  175. SIG sigIOComplete; // set (if valid) when IO on BF is completed
  176. SIG sigSyncIOComplete; // set (if valid) when sync IO on BF is completed
  177. union
  178. {
  179. ULONG cpageDirectRead; // count of prior BFs to be flushed
  180. ULONG cDepend; // count of prior BFs to be flushed
  181. };
  182. union
  183. {
  184. PAGE *ppageDirectRead;
  185. struct _bf *pbfDepend; // BF to be flushed after this one
  186. };
  187. LGPOS lgposRC; // log ptr to BeginT of oldest modifying xact
  188. LGPOS lgposModify; // log ptr of entry for last page modify
  189. struct _rce *prceDeferredBINext; // dbl link list for deferred before image.
  190. #ifdef COSTLY_PERF
  191. LONG lClass; // Table Class of which this BF is a member
  192. #endif // COSTLY_PERF
  193. HE rghe[2]; // 0 for buffer, 1 for history.
  194. HIST hist; // borrow the space in bf structure to keep HIST.
  195. #ifdef PCACHE_OPTIMIZATION
  196. //#if !defined( _X86_ ) || !defined( X86_USE_SEM )
  197. // BYTE rgbFiller[32];
  198. //#endif
  199. #ifndef COSTLY_PERF
  200. BYTE rgbFiller2[4]; // pad BF to 32 byte boundary
  201. #endif // !COSTLY_PERF
  202. #endif // PCACHE_OPTIMIZATION
  203. } BF;
  204. #define pbfNil ((BF *) 0)
  205. ERR ErrBFInit( VOID );
  206. VOID BFTerm( BOOL fNormal );
  207. #if defined( _X86_ ) && defined( X86_USE_SEM )
  208. VOID BFIEnterCriticalSection( BF *pbf );
  209. VOID BFILeaveCriticalSection( BF *pbf );
  210. STATIC INLINE VOID BFEnterCriticalSection( BF *pbf )
  211. {
  212. LONG volatile *plLock = &pbf->lLock;
  213. // use bit test and set instruction
  214. _asm
  215. {
  216. mov eax, plLock
  217. lock inc [eax]
  218. // If already set go to busy, otherwise return TRUE
  219. jnz busy
  220. } ;
  221. return;
  222. busy:
  223. BFIEnterCriticalSection( pbf );
  224. }
  225. STATIC INLINE VOID BFLeaveCriticalSection( BF *pbf )
  226. {
  227. LONG volatile *plLock = &pbf->lLock;
  228. _asm
  229. {
  230. mov eax, plLock
  231. lock dec [eax]
  232. jge wake
  233. }
  234. return;
  235. wake:
  236. BFILeaveCriticalSection( pbf );
  237. }
  238. #else
  239. extern int ccritBF;
  240. extern int critBFHashConst;
  241. extern CRIT *rgcritBF;
  242. #define IcritHash( ibf ) ((ibf) & critBFHashConst )
  243. #define BFEnterCriticalSection( pbf ) UtilEnterCriticalSection( rgcritBF[ IcritHash((ULONG)((ULONG_PTR)pbf) / sizeof(BF) ) ])
  244. #define BFLeaveCriticalSection( pbf ) UtilLeaveCriticalSection( rgcritBF[ IcritHash((ULONG)((ULONG_PTR)pbf) / sizeof(BF) ) ])
  245. #endif
  246. ERR ErrBFAccessPage( PIB *ppib, BF **ppbf, PN pn );
  247. ERR ErrBFReadAccessPage( FUCB *pfucb, PGNO pgno );
  248. ERR ErrBFWriteAccessPage( FUCB *pfucb, PGNO pgno );
  249. VOID BFAbandon( PIB *ppib, BF *pbf );
  250. VOID BFTossImmediate( PIB *ppib, BF *pbf );
  251. ERR ErrBFAllocPageBuffer( PIB *ppib, BF **ppbf, PN pn, LGPOS lgposRC, BYTE pgtyp );
  252. ERR ErrBFAllocTempBuffer( BF **ppbf );
  253. VOID BFFree( BF *pbf );
  254. VOID BFPreread( PN pn, CPG cpg, CPG *pcpgActual );
  255. VOID BFPrereadList( PN * rgpnPages, CPG *pcpgActual );
  256. ERR ErrBFDirectRead( DBID dbid, PGNO pgnoStart, PAGE *ppage, INT cpage );
  257. VOID BFDeferRemoveDependence( BF *pbf );
  258. #define fBFWait fFalse
  259. #define fBFNoWait fTrue
  260. ERR ErrBFRemoveDependence( PIB *ppib, BF *pbf, BOOL fNoWait );
  261. BOOL FBFCheckDependencyChain( BF *pbf );
  262. /* buffer flush prototype and flags
  263. /**/
  264. #define fBFFlushSome 0
  265. #define fBFFlushAll 1
  266. ERR ErrBFFlushBuffers( DBID dbid, LONG fBFFlush );
  267. STATIC INLINE VOID BFSFree( BF *pbf )
  268. {
  269. SgEnterCriticalSection( critBuf );
  270. BFFree( pbf );
  271. SgLeaveCriticalSection( critBuf );
  272. }
  273. /* the following small functions are called too often, */
  274. /* make it as a macros
  275. /**/
  276. DBID DbidOfPn( PN pn );
  277. PGNO PgnoOfPn( PN pn );
  278. #ifdef COSTLY_PERF
  279. extern unsigned long cBFClean[];
  280. extern unsigned long cBFNewDirties[];
  281. #else // !COSTLY_PERF
  282. extern unsigned long cBFClean;
  283. extern unsigned long cBFNewDirties;
  284. #endif // COSTLY_PERF
  285. #ifdef DEBUG
  286. VOID BFSetDirtyBit( BF *pbf );
  287. #else
  288. STATIC INLINE VOID BFSetDirtyBit( BF *pbf )
  289. {
  290. QWORD qwDBTime = QwPMDBTime( pbf->ppage );
  291. BFEnterCriticalSection( pbf );
  292. if ( !fRecovering && qwDBTime > QwDBHDRDBTime( rgfmp[ DbidOfPn(pbf->pn) ].pdbfilehdr ) )
  293. DBHDRSetDBTime( rgfmp[ DbidOfPn(pbf->pn) ].pdbfilehdr, qwDBTime );
  294. if ( !pbf->fDirty )
  295. {
  296. #ifdef COSTLY_PERF
  297. cBFClean[pbf->lClass]--;
  298. cBFNewDirties[pbf->lClass]++;
  299. #else // !COSTLY_PERF
  300. cBFClean--;
  301. cBFNewDirties++;
  302. #endif // COSTLY_PERF
  303. pbf->fDirty = fTrue;
  304. }
  305. BFLeaveCriticalSection( pbf );
  306. }
  307. #endif
  308. /* resets a BFs dirty flag
  309. /**/
  310. extern BOOL fLogDisabled;
  311. STATIC INLINE VOID BFResetDirtyBit( BF *pbf )
  312. {
  313. BFEnterCriticalSection( pbf );
  314. Assert( fRecovering ||
  315. pbf->fSyncWrite ||
  316. pbf->cWriteLatch == 0 );
  317. pbf->fVeryOld = fFalse;
  318. Assert( fLogDisabled || fRecovering || !rgfmp[DbidOfPn( pbf->pn )].fLogOn ||
  319. memcmp( &pbf->lgposRC, &lgposMax, sizeof( LGPOS ) ) != 0 );
  320. pbf->lgposRC = lgposMax;
  321. if ( pbf->fDirty )
  322. {
  323. #ifdef COSTLY_PERF
  324. cBFClean[pbf->lClass]++;
  325. #else // !COSTLY_PERF
  326. cBFClean++;
  327. #endif // COSTLY_PERF
  328. pbf->fDirty = fFalse;
  329. }
  330. BFLeaveCriticalSection( pbf );
  331. }
  332. STATIC INLINE VOID BFDirty( BF *pbf )
  333. {
  334. DBID dbid = DbidOfPn( pbf->pn );
  335. Assert( !pbf->fHold );
  336. BFSetDirtyBit( pbf );
  337. /* set ulDBTime for logging and also for multiple cursor
  338. /* maintenance, so that cursors can detect a change.
  339. /**/
  340. Assert( fRecovering ||
  341. dbid == dbidTemp ||
  342. QwPMDBTime( pbf->ppage ) <= QwDBHDRDBTime( rgfmp[dbid].pdbfilehdr ) );
  343. DBHDRIncDBTime( rgfmp[dbid].pdbfilehdr );
  344. PMSetDBTime( pbf->ppage, QwDBHDRDBTime( rgfmp[dbid].pdbfilehdr ) );
  345. }
  346. /* check if a page is dirty. If it is allocated for temp buffer, whose
  347. * pn must be Null, then no need to check if it is dirty since it will
  348. * not be written out.
  349. */
  350. #define AssertBFDirty( pbf ) \
  351. Assert( (pbf)->pn == pnNull || \
  352. (pbf) != pbfNil && (pbf)->fDirty == fTrue )
  353. #define AssertBFPin( pbf ) Assert( (pbf)->cPin > 0 )
  354. #define AssertBFWaitLatched( pbf, ppib ) \
  355. Assert( (pbf)->cWaitLatch > 0 \
  356. && (pbf)->cPin > 0 \
  357. && (pbf)->ppibWaitLatch == (ppib) );
  358. STATIC INLINE VOID BFPin( BF *pbf )
  359. {
  360. #ifdef DEBUG
  361. BFEnterCriticalSection( pbf );
  362. Assert( pbf != pbfNil );
  363. Assert( !pbf->fSyncRead );
  364. Assert( !pbf->fAsyncRead );
  365. Assert( pbf->cPin >= 0 );
  366. pbf->cPin++;
  367. BFLeaveCriticalSection( pbf );
  368. #else // !DEBUG
  369. UtilInterlockedIncrement( &pbf->cPin );
  370. #endif // DEBUG
  371. }
  372. STATIC INLINE VOID BFUnpin( BF *pbf )
  373. {
  374. #ifdef DEBUG
  375. BFEnterCriticalSection( pbf );
  376. Assert( pbf != pbfNil );
  377. Assert( !pbf->fSyncRead );
  378. Assert( !pbf->fAsyncRead );
  379. Assert( pbf->cPin > 0 );
  380. pbf->cPin--;
  381. BFLeaveCriticalSection( pbf );
  382. #else // !DEBUG
  383. UtilInterlockedDecrement( &pbf->cPin );
  384. #endif // DEBUG
  385. }
  386. STATIC INLINE VOID BFSetReadLatch( BF *pbf, PIB *ppib )
  387. {
  388. #ifdef READ_LATCH
  389. BFPin( pbf );
  390. Assert( pbf->cWriteLatch == 0 || pbf->ppibWriteLatch == ppib );
  391. pbf->cReadLatch++;
  392. #endif // READ_LATCH
  393. }
  394. STATIC INLINE VOID BFResetReadLatch( BF *pbf, PIB *ppib )
  395. {
  396. #ifdef READ_LATCH
  397. Assert( pbf->cReadLatch > 0 );
  398. Assert( pbf->cWriteLatch == 0 || pbf->ppibWriteLatch == ppib );
  399. pbf->cReadLatch--;
  400. BFUnpin( pbf );
  401. #endif // READ_LATCH
  402. }
  403. STATIC INLINE BOOL FBFReadLatchConflict( PIB *ppib, BF *pbf )
  404. {
  405. #ifdef READ_LATCH
  406. return pbf->cWriteLatch > 0 && pbf->ppibWriteLatch != ppib;
  407. #else // !READ_LATCH
  408. return fFalse;
  409. #endif // READ_LATCH
  410. }
  411. STATIC INLINE VOID BFSetWriteLatch( BF *pbf, PIB *ppib )
  412. {
  413. BFPin( pbf );
  414. #ifdef READ_LATCH
  415. Assert( pbf->cReadLatch == 0 );
  416. #endif // READ_LATCH
  417. Assert( pbf->cWriteLatch == 0 || pbf->ppibWriteLatch == ppib );
  418. pbf->cWriteLatch++;
  419. pbf->ppibWriteLatch = ppib;
  420. }
  421. STATIC INLINE VOID BFResetWriteLatch( BF *pbf, PIB *ppib )
  422. {
  423. #ifdef READ_LATCH
  424. Assert( pbf->cReadLatch == 0 );
  425. #endif // READ_LATCH
  426. Assert( pbf->cWriteLatch > 0 );
  427. Assert( pbf->ppibWriteLatch == ppib );
  428. pbf->cWriteLatch--;
  429. BFUnpin( pbf );
  430. }
  431. STATIC INLINE BOOL FBFWriteLatchConflict( PIB *ppib, BF *pbf )
  432. {
  433. return
  434. #ifdef READ_LATCH
  435. pbf->cReadLatch > 0 ||
  436. #endif // READ_LATCH
  437. ( pbf->cWriteLatch > 0 && pbf->ppibWriteLatch != ppib );
  438. }
  439. STATIC INLINE BOOL FBFWriteLatch( PIB *ppib, BF *pbf )
  440. {
  441. return pbf->cWriteLatch > 0 && pbf->ppibWriteLatch == ppib;
  442. }
  443. STATIC INLINE VOID BFSetWaitLatch( BF *pbf, PIB *ppib )
  444. {
  445. AssertCriticalSection( critJet );
  446. BFSetWriteLatch( pbf, ppib );
  447. Assert( pbf->cWaitLatch == 0 ||
  448. pbf->ppibWaitLatch == ppib );
  449. pbf->cWaitLatch++;
  450. pbf->ppibWaitLatch = ppib;
  451. }
  452. STATIC INLINE VOID BFResetWaitLatch( BF *pbf, PIB *ppib )
  453. {
  454. AssertCriticalSection( critJet );
  455. Assert( pbf->cWaitLatch > 0 );
  456. Assert( pbf->ppibWaitLatch == ppib );
  457. pbf->cWaitLatch--;
  458. BFResetWriteLatch( pbf, ppib );
  459. }
  460. ERR ErrBFDepend( BF *pbf, BF *pbfD );
  461. #ifdef DEBUG
  462. extern ERR ErrLGTrace( PIB *ppib, CHAR *sz );
  463. extern BOOL fDBGTraceBR;
  464. #endif
  465. STATIC INLINE VOID BFUndepend( BF *pbf )
  466. {
  467. if ( pbf->pbfDepend != pbfNil )
  468. {
  469. BF *pbfD = pbf->pbfDepend;
  470. #ifdef DEBUG
  471. if ( fDBGTraceBR )
  472. {
  473. char sz[256];
  474. sprintf( sz, "UD %ld:%ld->%ld:%ld(%lu)",
  475. DbidOfPn( pbf->pn ), PgnoOfPn( pbf->pn ),
  476. DbidOfPn( pbf->pbfDepend->pn), PgnoOfPn( pbf->pbfDepend->pn ),
  477. pbf->pbfDepend->cDepend );
  478. CallS( ErrLGTrace( ppibNil, sz ) );
  479. }
  480. #endif
  481. Assert( pbfD->cDepend > 0 );
  482. BFEnterCriticalSection( pbfD );
  483. pbfD->cDepend--;
  484. pbf->pbfDepend = pbfNil;
  485. BFLeaveCriticalSection( pbfD );
  486. }
  487. }
  488. /*
  489. * When ppib is not Nil and check if a page is in use by checking if it is
  490. * Accessible to this PIB. Note that a page is accessible even it is overlay
  491. * latched (cPin != 0). This checking accessible is mainly used by BFAccess.
  492. * If ppib is nil, basically it is used for freeing a buffer. This is used
  493. * by BFClean and BFIAlloc.
  494. */
  495. STATIC INLINE BOOL FBFNotAccessible( PIB *ppib, BF *pbf )
  496. {
  497. return pbf->fAsyncRead ||
  498. pbf->fSyncRead ||
  499. pbf->fAsyncWrite ||
  500. pbf->fSyncWrite ||
  501. pbf->fHold ||
  502. ( pbf->cWaitLatch != 0 && ppib != pbf->ppibWaitLatch );
  503. }
  504. STATIC INLINE BOOL FBFNotAvail( BF *pbf )
  505. {
  506. return pbf->fAsyncRead ||
  507. pbf->fSyncRead ||
  508. pbf->fAsyncWrite ||
  509. pbf->fSyncWrite ||
  510. pbf->fHold ||
  511. pbf->cPin != 0;
  512. }
  513. STATIC INLINE BOOL FBFInUse( PIB *ppib, BF *pbf )
  514. {
  515. return ppib != ppibNil ? FBFNotAccessible( ppib, pbf ) : FBFNotAvail( pbf );
  516. }
  517. STATIC INLINE BOOL FBFInUseByOthers( PIB *ppib, BF *pbf )
  518. {
  519. return pbf->fAsyncRead ||
  520. pbf->fSyncRead ||
  521. pbf->fAsyncWrite ||
  522. pbf->fSyncWrite ||
  523. pbf->fHold ||
  524. pbf->cPin > 1 ||
  525. ( pbf->cWaitLatch != 0 && ppib != pbf->ppibWaitLatch ) ||
  526. ( pbf->cWriteLatch != 0 && ppib != pbf->ppibWriteLatch );
  527. }
  528. //---- STORAGE (storage.c) -------------------------------------------------
  529. ERR ErrFMPSetDatabases( PIB *ppib );
  530. extern BOOL fGlobalFMPLoaded;
  531. ERR ErrFMPInit( VOID );
  532. VOID FMPTerm( );
  533. #ifdef DEBUG
  534. VOID ITDBGSetConstants();
  535. #endif
  536. ERR ErrITSetConstants( VOID );
  537. ERR ErrITInit( VOID );
  538. #define fTermCleanUp 0x00000001 /* Termination with OLC, Version clean up etc */
  539. #define fTermNoCleanUp 0x00000002 /* Termination without any clean up */
  540. #define fTermError 0x00000004 /* Terminate with error, no OLC clean up, */
  541. /* no flush buffers, db header */
  542. ERR ErrITTerm( INT fTerm );
  543. ERR ErrBFNewPage( FUCB *pfucb, PGNO pgno, PGTYP pgtyp, PGNO pgnoFDP );
  544. VOID BFSleep( unsigned long ulMSecs );
  545. STATIC INLINE PN PnOfDbidPgno( DBID dbid, PGNO pgno )
  546. {
  547. return (PN) ( ( (PN) dbid << 24 ) | (PN) pgno );
  548. }
  549. STATIC INLINE DBID DbidOfPn( PN pn )
  550. {
  551. return (DBID) ( ( (BYTE *) &pn )[3] );
  552. }
  553. STATIC INLINE PGNO PgnoOfPn( PN pn )
  554. {
  555. return (PGNO) ( pn & 0x00FFFFFF );
  556. }
  557. VOID BFReference( BF *pbf, PIB *ppib );
  558. #define FBFReadAccessPage FBFAccessPage
  559. #define FBFWriteAccessPage FBFAccessPage
  560. STATIC INLINE BOOL FBFAccessPage( FUCB *pfucb, PGNO pgno )
  561. {
  562. BOOL fAccessible;
  563. BF *pbf = pfucb->ssib.pbf;
  564. AssertCriticalSection( critJet );
  565. Assert( pfucb->ppib != ppibNil );
  566. if ( pbf == pbfNil )
  567. return fFalse;
  568. /* if the cached BF's PN is the same and it is accessible and it is in
  569. /* the LRUK heap or list, we can access the page
  570. /**/
  571. BFEnterCriticalSection( pbf );
  572. fAccessible = ( pbf->pn == PnOfDbidPgno( pfucb->dbid, pgno ) &&
  573. !FBFNotAccessible( pfucb->ppib, pbf ) &&
  574. pbf->fInLRUK );
  575. BFLeaveCriticalSection( pbf );
  576. #ifdef LRU1
  577. BFReference( pbf, pfucb->ppib );
  578. #else // !LRU1
  579. /* if this is not a correlated access, this counts as a BF reference
  580. /**/
  581. if ( fAccessible && pbf->trxLastRef != pfucb->ppib->trxBegin0 )
  582. BFReference( pbf, pfucb->ppib );
  583. #endif // LRU1
  584. return fAccessible;
  585. }
  586. #ifdef DEBUG
  587. #define AssertFBFReadAccessPage AssertFBFAccessPage
  588. #define AssertFBFWriteAccessPage AssertFBFAccessPage
  589. STATIC VOID AssertFBFAccessPage( FUCB *pfucb, PGNO pgno )
  590. {
  591. BF *pbf = pfucb->ssib.pbf;
  592. AssertCriticalSection( critJet );
  593. Assert( pfucb->ppib != ppibNil );
  594. Assert( pbf != pbfNil );
  595. /* if the cached BF's PN is the same and it is accessible and it is in
  596. /* the LRUK heap or list, we can access the page
  597. /**/
  598. BFEnterCriticalSection( pbf );
  599. Assert( pbf->pn == PnOfDbidPgno( pfucb->dbid, pgno ) );
  600. Assert( !FBFNotAccessible( pfucb->ppib, pbf ) );
  601. Assert( pbf->fInLRUK );
  602. BFLeaveCriticalSection( pbf );
  603. }
  604. #else // !DEBUG
  605. #define AssertFBFReadAccessPage( pfucbX, pgnoX )
  606. #define AssertFBFWriteAccessPage( pfucbX, pgnoX )
  607. #endif // DEBUG
  608. //---- PAGE (page.c) --------------------------------------------------------
  609. STATIC INLINE QWORD QwSTDBTimePssib( SSIB *pssib )
  610. {
  611. return QwPMDBTime( pssib->pbf->ppage );
  612. }
  613. STATIC INLINE VOID PMSetQwDBTime( SSIB *pssib, QWORD qw )
  614. {
  615. Assert( qw <= QwDBHDRDBTime( rgfmp[DbidOfPn( pssib->pbf->pn )].pdbfilehdr ) );
  616. PMSetDBTime( pssib->pbf->ppage, qw );
  617. }
  618. STATIC INLINE VOID BFSetQwDBTime( BF *pbf, QWORD qw )
  619. {
  620. Assert( qw <= QwDBHDRDBTime( rgfmp[DbidOfPn( pbf->pn )].pdbfilehdr ) );
  621. PMSetDBTime( pbf->ppage, qw );
  622. }
  623. #ifdef DEBUG
  624. VOID AssertPMGet( SSIB *pssib, LONG itag );
  625. #else
  626. #define AssertPMGet( pssib, itag )
  627. #endif
  628. // End Assert redirection
  629. #undef szAssertFilename
  630. #endif // _STAPI_H