@@ -5153,6 +5153,8 @@ LOCAL VOID DBUTLIReportSpaceLeakEstimationSucceeded(
51535153 const CPG cpgSplitBuffers,
51545154 const ULONG cCachedPrimary,
51555155 const ULONG cUncachedPrimary,
5156+ const ULONG cEnumerationConflictsSucceeded,
5157+ const ULONG cEnumerationConflictsFailed,
51565158 const JET_THREADSTATS& jts,
51575159 const ULONG ulMinElapsed,
51585160 const double dblSecElapsed )
@@ -5189,7 +5191,9 @@ LOCAL VOID DBUTLIReportSpaceLeakEstimationSucceeded(
51895191 OSFormatW ( L" %u" , cUncachedPrimary ),
51905192 OSFormatW ( L" %u" , jts.cPageRead ), OSFormatW ( L" %u" , jts.cPagePreread ), OSFormatW ( L" %u" , jts.cPageReferenced ), OSFormatW ( L" %u" , jts.cPageDirtied ), OSFormatW ( L" %u" , jts.cPageRedirtied ),
51915193 OSFormatW ( L" %u" , ulMinElapsed ), OSFormatW ( L" %.3f" , dblSecElapsed ),
5192- OSFormatW ( L" %d" , cpgOwnedPrimaryCorrection ), OSFormatW ( L" %I64d" , pfmp->CbOfCpgSigned ( cpgOwnedPrimaryCorrection ) ), ( ( cpgOwnedPrimaryOriginal != 0 ) ? OSFormatW ( L" %.3f" , ( 100.0 * (double )cpgOwnedPrimaryCorrection ) / (double )cpgOwnedPrimaryOriginal ) : L" -" )
5194+ OSFormatW ( L" %d" , cpgOwnedPrimaryCorrection ), OSFormatW ( L" %I64d" , pfmp->CbOfCpgSigned ( cpgOwnedPrimaryCorrection ) ), ( ( cpgOwnedPrimaryOriginal != 0 ) ? OSFormatW ( L" %.3f" , ( 100.0 * (double )cpgOwnedPrimaryCorrection ) / (double )cpgOwnedPrimaryOriginal ) : L" -" ),
5195+ OSFormatW ( L" %u" , cEnumerationConflictsSucceeded ),
5196+ OSFormatW ( L" %u" , cEnumerationConflictsFailed )
51935197 };
51945198 UtilReportEvent (
51955199 eventInformation,
@@ -5245,6 +5249,8 @@ LOCAL ERR ErrDBUTLIEstimateRootSpaceLeak( PIB* const ppib, const IFMP ifmp )
52455249 BOOL fRunning = fFalse ;
52465250 JET_THREADSTATS jtsStart = { 0 }, jtsEnd = { 0 };
52475251 OBJID objidLast = objidNil;
5252+ PGNO pgnoFDPLast = pgnoNull;
5253+ ULONG cEnumerationConflictsFailed = 0 , cEnumerationConflictsSucceeded = 0 ;
52485254 CPG cpgOwnedPrimary = 0 , cpgOwnedPrimaryCorrection = 0 ;
52495255 ULONG cCachedPrimary = 0 , cUncachedPrimary = 0 ;
52505256 CPG cpgUsedRoot = 0 , cpgUsedOe = 0 , cpgUsedAe = 0 ;
@@ -5277,9 +5283,9 @@ LOCAL ERR ErrDBUTLIEstimateRootSpaceLeak( PIB* const ppib, const IFMP ifmp )
52775283 ppib->SetFSessionLeakReport ();
52785284
52795285 CHAR szObjectName[ JET_cbNameMost + 1 ];
5280- for ( err = ErrCATGetNextRootObject ( ppib, ifmp, fTrue , &pfucbCatalog, &objidLast, szObjectName );
5286+ for ( err = ErrCATGetNextRootObject ( ppib, ifmp, fTrue , &pfucbCatalog, &objidLast, &pgnoFDPLast, szObjectName );
52815287 ( err >= JET_errSuccess ) && ( objidLast != objidNil );
5282- err = ErrCATGetNextRootObject ( ppib, ifmp, fTrue , &pfucbCatalog, &objidLast, szObjectName ) )
5288+ err = ErrCATGetNextRootObject ( ppib, ifmp, fTrue , &pfucbCatalog, &objidLast, &pgnoFDPLast, szObjectName ) )
52835289 {
52845290#ifdef DEBUG
52855291 Assert ( objidLast != objidSystemRoot ); // Root object is not supposed to be returned here.
@@ -5307,37 +5313,111 @@ LOCAL ERR ErrDBUTLIEstimateRootSpaceLeak( PIB* const ppib, const IFMP ifmp )
53075313 // Test injection.
53085314 OnDebug ( while ( objidLast >= (OBJID)UlConfigOverrideInjection ( 48550 , objidFDPOverMax ) ) );
53095315
5310- err = ErrFILEOpenTable ( ppib, ifmp, &pfucbTable, szObjectName, JET_bitTableReadOnly | JET_bitTableTryPurgeOnClose );
5311- if ( err == JET_errObjectNotFound )
5316+ BOOL fRetried = fFalse , fRetry = fFalse ;
5317+ const BOOL fInfiniteRetries = OnDebugOrRetail ( fTrue , fFalse );
5318+ ERR errRetry = JET_errSuccess;
5319+ const CHAR* wszRetryReason = " " ;
5320+ do
53125321 {
5313- err = JET_errSuccess;
5314- }
5315- else
5316- {
5317- Call ( err );
5322+ fRetried = fRetry ;
5323+ if ( fRetry )
5324+ {
5325+ UtilSleep ( 10 );
5326+ fRetry = fFalse ;
5327+ }
53185328
5319- cUncachedPrimary++;
5320-
5321- // Test injection.
5322- OnDebug ( while ( objidLast >= (OBJID)UlConfigOverrideInjection ( 57894 , objidFDPOverMax ) ) );
5329+ err = ErrFILEOpenTable ( ppib, ifmp, &pfucbTable, szObjectName, JET_bitTableReadOnly | JET_bitTableTryPurgeOnClose );
5330+ if ( ( err == JET_errObjectNotFound ) || ( err == JET_errTableLocked ) )
5331+ {
5332+ // We are probably racing with table deletion.
5333+ FCBStateFlags fcbsf = fcbsfNone;
5334+ const BOOL fFoundFcb = ( FCB::PfcbFCBGet ( ifmp, pgnoFDPLast, &fcbsf, fFalse /* fIncrementRefCount */ , fTrue /* fInitForRecovery */ ) != pfcbNil );
5335+ const BOOL fDeletePending = fFoundFcb && ( fcbsf & fcbsfDeletePending );
53235336
5324- Call ( ErrSPGetInfo (
5325- ppib,
5326- ifmp,
5327- pfucbTable,
5328- (BYTE*)&cpgPrimaryObject,
5329- sizeof ( cpgPrimaryObject ),
5330- fSPOwnedExtent ,
5331- gci::Allow ) );
5337+ if ( fFoundFcb && !fDeletePending )
5338+ {
5339+ // This is unexpected if we know the table is actually getting deleted.
5340+ Assert ( err != JET_errObjectNotFound );
5341+ fRetry = fTrue ;
5342+ wszRetryReason = " DelNotPending" ;
5343+ }
5344+ else if ( fFoundFcb && fDeletePending )
5345+ {
5346+ // Table deletion is still pending.
5347+ fRetry = fTrue ;
5348+ wszRetryReason = " DelPending" ;
53325349
5333- cpgOwnedPrimary += cpgPrimaryObject;
5350+ // Perform cleanup.
5351+ (void )PverFromPpib ( ppib )->ErrVERRCEClean ( ifmp );
5352+ }
5353+ else
5354+ {
5355+ Assert ( !fFoundFcb );
5356+ if ( err == JET_errTableLocked )
5357+ {
5358+ // Either the version store entry for the table deletion has cleared,
5359+ // or an exclusive user released the table and the FCB got purged.
5360+ fRetry = fTrue ;
5361+ wszRetryReason = " FcbNotFound" ;
5362+ }
5363+ else
5364+ {
5365+ // Version store entry for the table deletion has cleared.
5366+ // No need to retry.
5367+ Assert ( err == JET_errObjectNotFound );
5368+ }
5369+ }
53345370
5335- Call ( ErrFILECloseTable ( ppib, pfucbTable ) );
5336- pfucbTable = pfucbNil;
5337- }
5371+ errRetry = err;
5372+ err = JET_errSuccess;
5373+ }
5374+ else
5375+ {
5376+ Assert ( !fRetry );
5377+ Call ( err );
5378+
5379+ cUncachedPrimary++;
53385380
5339- Assert ( pfucbTable == pfucbNil );
5381+ // Test injection.
5382+ OnDebug ( while ( objidLast >= (OBJID)UlConfigOverrideInjection ( 57894 , objidFDPOverMax ) ) );
5383+
5384+ Call ( ErrSPGetInfo (
5385+ ppib,
5386+ ifmp,
5387+ pfucbTable,
5388+ (BYTE*)&cpgPrimaryObject,
5389+ sizeof ( cpgPrimaryObject ),
5390+ fSPOwnedExtent ,
5391+ gci::Allow ) );
5392+
5393+ cpgOwnedPrimary += cpgPrimaryObject;
5394+
5395+ Call ( ErrFILECloseTable ( ppib, pfucbTable ) );
5396+ pfucbTable = pfucbNil;
5397+ }
5398+
5399+ if ( fRetried )
5400+ {
5401+ if ( fRetry )
5402+ {
5403+ cEnumerationConflictsFailed++;
5404+ if ( !fInfiniteRetries )
5405+ {
5406+ FireWall ( OSFormat ( " LeakReportConflict:%s:%d" , wszRetryReason, errRetry ) );
5407+ }
5408+ }
5409+ else
5410+ {
5411+ cEnumerationConflictsSucceeded++;
5412+ }
5413+ }
5414+
5415+ Assert ( pfucbTable == pfucbNil );
5416+ Assert ( err >= JET_errSuccess );
5417+ }
5418+ while ( fRetry && ( !fRetried || fInfiniteRetries ) );
53405419 }
5420+
53415421 pfmp->SetOjidLeakEstimation ( objidLast );
53425422
53435423#ifdef DEBUG
@@ -5506,6 +5586,8 @@ LOCAL ERR ErrDBUTLIEstimateRootSpaceLeak( PIB* const ppib, const IFMP ifmp )
55065586 rgcpgRootSpaceInfo[ 2 ], // cpgSplitBuffers
55075587 cCachedPrimary,
55085588 cUncachedPrimary,
5589+ cEnumerationConflictsSucceeded,
5590+ cEnumerationConflictsFailed,
55095591 jts,
55105592 ulMinElapsed,
55115593 dblSecElapsed );
0 commit comments