2.1.4.12 Algorithm to Check for an Oplock Break

The inputs for this algorithm are:

  • Open: The Open being used in the request calling this algorithm.

  • Oplock: The Oplock being checked.

  • Operation: A code describing the operation being processed.

  • OpParams: Parameters associated with the Operation code that are passed in from the calling request. For example, if Operation is OPEN, as specified in section 2.1.5.1, then OpParams will have the members DesiredAccess and CreateDisposition. Each of these is a parameter to the open request as specified in section 2.1.5.1. This parameter could be empty, depending on the Operation code.

  • Flags: An optional parameter. If unspecified it is considered to contain 0. Valid nonzero values are:

    • PARENT_OBJECT

The algorithm uses the following local variables:

  • Boolean values (initialized to FALSE): BreakToTwo, BreakToNone, NeedToWait

  • BreakCacheState – MAY contain 0 or a combination of one or more of READ_CACHING, WRITE_CACHING, or HANDLE_CACHING, as specified in section 2.1.1.10.  Initialized to 0.

    • Note that there are only four legal nonzero combinations of flags for BreakCacheState:

      • (READ_CACHING|WRITE_CACHING|HANDLE_CACHING)

      • (READ_CACHING|WRITE_CACHING)

      • WRITE_CACHING

      • HANDLE_CACHING

  • OPERATION_MASK – a constant that MUST contain the following value:

    • (LEVEL_ONE_OPLOCK|LEVEL_TWO_OPLOCK|BATCH_OPLOCK|READ_CACHING|WRITE_CACHING|HANDLE_CACHING)

Pseudocode for the algorithm is as follows:

If Oplock is not empty and Oplock.State is not NO_OPLOCK:

  • If Flags contains PARENT_OBJECT<42>:

    • Set BreakCacheState to (READ_CACHING|WRITE_CACHING).

  • Else:

    • Switch (Operation):

      • Case OPEN, as specified in section 2.1.5.1:

        • If (((OpParams.DesiredAccess contains no flags other than FILE_READ_ATTRIBUTES, FILE_WRITE_ATTRIBUTES, READ_CONTROL, or SYNCHRONIZE) and (Oplock.State anded with OPERATION_MASK) contains no flags other than READ_CACHING, WRITE_CACHING, or HANDLE_CACHING)) or ((OpParams.DesiredAccess contains no flags other than FILE_READ_ATTRIBUTES, FILE_WRITE_ATTRIBUTES or SYNCHRONIZE) and (Oplock.State anded with OPERATION_MASK) contains no flags other than LEVEL_TWO_OPLOCK, LEVEL_ONE_OPLOCK or BATCH_OPLOCK))), the algorithm returns at this point.

        • EndIf

        • If OpParams.CreateDisposition is FILE_SUPERSEDE, FILE_OVERWRITE, or FILE_OVERWRITE_IF:

          • Set BreakToNone to TRUE, set BreakCacheState to (READ_CACHING|WRITE_CACHING).

        • Else

          • Set BreakToTwo to TRUE, set BreakCacheState to WRITE_CACHING.

        • EndIf

      • EndCase

      • Case OPEN_BREAK_H, as specified in section 2.1.5.1.2:

        • Set BreakCacheState to HANDLE_CACHING.

      • EndCase

      • Case CLOSE, as specified in section 2.1.5.5:

        • If Oplock.IIOplocks is not empty:

          • For each Open ThisOpen in Oplock.IIOplocks:

            • If ThisOpen == Open:

              • Remove ThisOpen from Oplock.IIOplocks.

              • Notify the server of an oplock break according to the algorithm in section 2.1.5.18.3, setting the algorithm's parameters as follows:

                • BreakingOplockOpen equal to ThisOpen.

                • NewOplockLevel equal to LEVEL_NONE.

                • AcknowledgeRequired equal to FALSE.

                • OplockCompletionStatus equal to STATUS_SUCCESS.

              • (The operation does not end at this point; this call to 2.1.5.18.3 completes some earlier call to 2.1.5.18.2.)

            • EndIf

          • EndFor

          • Recompute Oplock.State according to the algorithm in section 2.1.4.13, passing Oplock as the ThisOplock parameter.

        • EndIf

        • If Oplock.ROplocks is not empty:

          • For each Open ThisOpen in Oplock.ROplocks:

            • If ThisOpen == Open:

              • Remove ThisOpen from Oplock.ROplocks.

              • Notify the server of an oplock break according to the algorithm in section 2.1.5.18.3, setting the algorithm's parameters as follows:

                • BreakingOplockOpen equal to ThisOpen.

                • NewOplockLevel equal to LEVEL_NONE.

                • AcknowledgeRequired equal to FALSE.

                • OplockCompletionStatus equal to STATUS_OPLOCK_HANDLE_CLOSED.

              • (The operation does not end at this point; this call to 2.1.5.18.3 completes some earlier call to 2.1.5.18.2.)

            • EndIf

          • EndFor

          • Recompute Oplock.State according to the algorithm in section 2.1.4.13, passing Oplock as the ThisOplock parameter.

        • EndIf

        • If Oplock.RHOplocks is not empty:

          • For each Open ThisOpen in Oplock.RHOplocks:

            • If ThisOpen == Open:

              • Remove ThisOpen from Oplock.RHOplocks.

              • Notify the server of an oplock break according to the algorithm in section 2.1.5.18.3, setting the algorithm's parameters as follows:

                • BreakingOplockOpen equal to ThisOpen.

                • NewOplockLevel equal to LEVEL_NONE.

                • AcknowledgeRequired equal to FALSE.

                • OplockCompletionStatus equal to STATUS_OPLOCK_HANDLE_CLOSED.

              • (The operation does not end at this point; this call to 2.1.5.18.3 completes some earlier call to 2.1.5.18.2.)

            • EndIf

          • EndFor

          • Recompute Oplock.State according to the algorithm in section 2.1.4.13, passing Oplock as the ThisOplock parameter.

        • EndIf

        • If Oplock.RHBreakQueue is not empty:

          • For each RHOpContext ThisContext in Oplock.RHBreakQueue:

            • If ThisContext.Open == Open:

              • Remove ThisContext from Oplock.RHBreakQueue.

            • EndIf

          • EndFor

          • Recompute Oplock.State according to the algorithm in section 2.1.4.13, passing Oplock as the ThisOplock parameter.

          • For each Open WaitingOpen on Oplock.WaitList:

            • If Oplock.RHBreakQueue is empty:

              • Indicate that the operation associated with WaitingOpen can continue according to the algorithm in section 2.1.4.12.1, setting OpenToRelease equal to WaitingOpen.

              • Remove WaitingOpen from Oplock.WaitList.

            • Else

              • If the value on every RHOpContext.Open.TargetOplockKey on Oplock.RHBreakQueue is equal to WaitingOpen .TargetOplockKey:

                • Indicate that the operation associated with WaitingOpen can continue according to the algorithm in section 2.1.4.12.1, setting OpenToRelease equal to WaitingOpen.

                • Remove WaitingOpen from Oplock.WaitList.

              • EndIf

            • EndIf

          • EndFor

        • EndIf

        • If Open equals Oplock.ExclusiveOpen

          • If Oplock.State contains none of BREAK_TO_TWO, BREAK_TO_NONE, BREAK_TO_TWO_TO_NONE, BREAK_TO_READ_CACHING, BREAK_TO_WRITE_CACHING, BREAK_TO_HANDLE_CACHING, or BREAK_TO_NO_CACHING:

            • Notify the server of an oplock break according to the algorithm in section 2.1.5.18.3, setting the algorithm's parameters as follows:

              • BreakingOplockOpen equal to Oplock.ExclusiveOpen.

              • NewOplockLevel equal to LEVEL_NONE.

              • AcknowledgeRequired equal to FALSE.

              • OplockCompletionStatus equal to:

                • STATUS_OPLOCK_HANDLE_CLOSED if Oplock.State contains any of READ_CACHING, WRITE_CACHING, or HANDLE_CACHING.

                • STATUS_SUCCESS otherwise.

            • (The operation does not end at this point; this call to 2.1.5.18.3 completes some earlier call to 2.1.5.18.1.)

          • EndIf

          • Set Oplock.ExclusiveOpen to NULL.

          • Set Oplock.State to NO_OPLOCK.

          • For each Open WaitingOpen on Oplock.WaitList:

            • Indicate that the operation associated with WaitingOpen can continue according to the algorithm in section 2.1.4.12.1, setting OpenToRelease equal to WaitingOpen.

            • Remove WaitingOpen from Oplock.WaitList.

          • EndFor

        • EndIf

      • EndCase

      • Case READ, as specified in section 2.1.5.3:

        • Set BreakToTwo to TRUE

        • Set BreakCacheState to WRITE_CACHING.

      • EndCase

      • Case FLUSH_DATA, as specified in section 2.1.5.7:

        • Set BreakToTwo to TRUE

        • Set BreakCacheState to WRITE_CACHING.

      • EndCase

      • Case LOCK_CONTROL, as specified in section 2.1.5.8:

      • Case WRITE, as specified in section 2.1.5.4:

        • Set BreakToNone to TRUE

        • Set BreakCacheState to (READ_CACHING|WRITE_CACHING).

      • EndCase

      • Case SET_INFORMATION, as specified in section 2.1.5.15:

        • Switch (OpParams.FileInformationClass):

          • Case FileEndOfFileInformation:

          • Case FileAllocationInformation:

            • Set BreakToNone to TRUE

            • Set BreakCacheState to (READ_CACHING|WRITE_CACHING).

          • EndCase

          • Case FileRenameInformation:

          • Case FileLinkInformation:

          • Case FileShortNameInformation:

            • Set BreakCacheState to HANDLE_CACHING.

            • If Oplock.State contains BATCH_OPLOCK, set BreakToNone to TRUE.

          • EndCase

          • Case FileDispositionInformation:

            • If OpParams.DeleteFile is TRUE,

            • Set BreakCacheState to HANDLE_CACHING.

          • EndCase

        • EndSwitch // FileInfoClass

        • Case FS_CONTROL, as specified in section 2.1.5.10:

          • If OpParams.ControlCode is FSCTL_SET_ZERO_DATA:

            • Set BreakToNone to TRUE.

            • Set BreakCacheState to (READ_CACHING|WRITE_CACHING).

          • EndIf

        • EndCase

        • Case SET_SECURITY, as specified in section 2.1.5.17

          • Set BreakCacheState to HANDLE_CACHING

        • EndCase

    • EndSwitch // Operation

  • EndIf

  • If BreakToTwo is TRUE:

    • If (Oplock.State != LEVEL_TWO_OPLOCK) and

      ((Oplock.ExclusiveOpen is empty) or

      (Oplock.ExclusiveOpen.TargetOplockKey != Open.TargetOplockKey)):

      • If (Oplock.State contains EXCLUSIVE) and

        (Oplock.State contains none of READ_CACHING, WRITE_CACHING, or HANDLE_CACHING):

        • If Oplock.State contains none of BREAK_TO_TWO, BREAK_TO_NONE, BREAK_TO_TWO_TO_NONE, BREAK_TO_READ_CACHING, BREAK_TO_WRITE_CACHING, BREAK_TO_HANDLE_CACHING, or BREAK_TO_NO_CACHING:

          • // Oplock.State MUST contain either LEVEL_ONE_OPLOCK or BATCH_OPLOCK.

          • Set BREAK_TO_TWO in Oplock.State.

          • Notify the server of an oplock break according to the algorithm in section 2.1.5.18.3, setting the algorithm's parameters as follows:

            • BreakingOplockOpen equal to Oplock.ExclusiveOpen.

            • NewOplockLevel equal to LEVEL_TWO.

            • AcknowledgeRequired equal to TRUE.

            • OplockCompletionStatus equal to STATUS_SUCCESS.

          • (The operation does not end at this point; this call to 2.1.5.18.3 completes some earlier call to 2.1.5.18.1.)

        • EndIf

        • The operation that called this algorithm MUST be made cancelable by inserting it into CancelableOperations.CancelableOperationList.

        • Insert Open into Oplock.WaitList.

        • The operation that called this algorithm waits until the oplock break is acknowledged, as specified in section 2.1.5.19, or the operation is canceled.

      • EndIf

    • EndIf

  • Else If BreakToNone is TRUE:

    • If (Oplock.State == LEVEL_TWO_OPLOCK) or

      (Oplock.ExclusiveOpen is empty) or

      (Oplock.ExclusiveOpen.TargetOplockKey != Open.TargetOplockKey):

      • If (Oplock.State != NO_OPLOCK) and

        (Oplock.State contains neither WRITE_CACHING nor HANDLE_CACHING):

        • If Oplock.State contains none of LEVEL_TWO_OPLOCK, BREAK_TO_TWO, BREAK_TO_NONE, BREAK_TO_TWO_TO_NONE, BREAK_TO_READ_CACHING, BREAK_TO_WRITE_CACHING, BREAK_TO_HANDLE_CACHING, or BREAK_TO_NO_CACHING:

          • // There could be a READ_CACHING-only oplock here. Those are broken later on.

          • If Oplock.State contains READ_CACHING, go to the LeaveBreakToNone label.

          • Set BREAK_TO_NONE in Oplock.State.

          • Notify the server of an oplock break according to the algorithm in section 2.1.5.18.3, setting the algorithm's parameters as follows:

            • BreakingOplockOpen equal to Oplock.ExclusiveOpen.

            • NewOplockLevel equal to LEVEL_NONE.

            • AcknowledgeRequired equal to TRUE.

            • OplockCompletionStatus equal to STATUS_SUCCESS.

          • (The operation does not end at this point; this call to 2.1.5.18.3 completes some earlier call to 2.1.5.18.1.)

        • Else If Oplock.State equals LEVEL_TWO_OPLOCK or (LEVEL_TWO_OPLOCK|READ_CACHING):

          • For each Open ThisOpen in Oplock.IIOplocks:

            • Remove ThisOpen from Oplock.IIOplocks.

            • Notify the server of an oplock break according to the algorithm in section 2.1.5.18.3, setting the algorithm's parameters as follows:

              • BreakingOplockOpen equal to ThisOpen.

              • NewOplockLevel equal to LEVEL_NONE.

              • AcknowledgeRequired equal to FALSE.

              • OplockCompletionStatus equal to STATUS_SUCCESS.

            • (The operation does not end at this point; this call to 2.1.5.18.3 completes some earlier call to 2.1.5.18.2.)

          • EndFor

          • If Oplock.State equals (LEVEL_TWO_OPLOCK|READ_CACHING):

            • Set Oplock.State equal to READ_CACHING.

          • Else

            • Set Oplock.State equal to NO_OPLOCK.

          • EndIf

          • Go to the LeaveBreakToNone label.

        • Else If Oplock.State contains BREAK_TO_TWO:

          • Clear BREAK_TO_TWO from Oplock.State.

          • Set BREAK_TO_TWO_TO_NONE in Oplock.State.

        • EndIf

        • If Oplock.ExclusiveOpen is not empty, and Oplock.ExclusiveOpen.TargetOplockKey equals Open.TargetOplockKey, go to the LeaveBreakToNone label.

        • The operation that called this algorithm MUST be made cancelable by inserting it into CancelableOperations.CancelableOperationList.

        • Insert Open into Oplock.WaitList.

        • The operation that called this algorithm waits until the oplock break is acknowledged, as specified in section 2.1.5.19, or the operation is canceled.

      • EndIf

    • EndIf

  • EndIf

    LeaveBreakToNone (goto destination label):

  • If BreakCacheState is not 0:

    • If Oplock.State contains any flags that are in BreakCacheState:

      • If Oplock.ExclusiveOpen is not empty, call the algorithm in section 2.1.4.12.2, passing Open as the OperationOpen parameter, Oplock.ExclusiveOpen as the OplockOpen parameter, and Flags as the Flags parameter. If the algorithm returns TRUE:

        • The algorithm returns at this point.

      • Switch (Oplock.State):

        • Case (READ_CACHING|HANDLE_CACHING|MIXED_R_AND_RH):

        • Case READ_CACHING:

        • Case (LEVEL_TWO_OPLOCK|READ_CACHING):

          • If BreakCacheState contains READ_CACHING:

            • For each Open ThisOpen in Oplock.ROplocks:

              • Call the algorithm in section 2.1.4.12.2, passing Open as the OperationOpen parameter, ThisOpen as the OplockOpen parameter, and Flags as the Flags parameter. If the algorithm returns FALSE:

                • Remove ThisOpen from Oplock.ROplocks.

                • Notify the server of an oplock break according to the algorithm in section 2.1.5.18.3, setting the algorithm's parameters as follows:

                  • BreakingOplockOpen equal to ThisOpen.

                  • NewOplockLevel equal to LEVEL_NONE.

                  • AcknowledgeRequired equal to FALSE.

                  • OplockCompletionStatus equal to STATUS_SUCCESS.

                • (The operation does not end at this point; this call to 2.1.5.18.3 completes some earlier call to 2.1.5.18.2.)

              • EndIf

            • EndFor

          • EndIf

          • If Oplock.State equals (READ_CACHING|HANDLE_CACHING|MIXED_R_AND_RH):

            • // Do nothing; FALL THROUGH to next Case statement.

          • Else

            • Recompute Oplock.State according to the algorithm in section 2.1.4.13, passing Oplock as the ThisOplock parameter.

            • EndCase

          • EndIf

        • Case (READ_CACHING|HANDLE_CACHING):

          • If BreakCacheState equals HANDLE_CACHING:

            • For each Open ThisOpen in Oplock.RHOplocks:

              • If ThisOpen.OplockKey does not equal Open.OplockKey:

                • Remove ThisOpen from Oplock.RHOplocks.

                • Notify the server of an oplock break according to the algorithm in section 2.1.5.18.3, setting the algorithm's parameters as follows:

                  • BreakingOplockOpen equal to ThisOpen.

                  • NewOplockLevel equal to READ_CACHING.

                  • AcknowledgeRequired equal to TRUE.

                  • OplockCompletionStatus equal to STATUS_SUCCESS.

                • (The operation does not end at this point; this call to 2.1.5.18.3 completes some earlier call to 2.1.5.18.2.)

                • Initialize a new RHOpContext object, setting its fields as follows:

                  • RHOpContext.Open set to ThisOpen.

                  • RHOpContext.BreakingToRead to TRUE.

                • Add the new RHOpContext object to Oplock.RHBreakQueue.

                • Set NeedToWait to TRUE.

              • EndIf

            • EndFor

          • Else If BreakCacheState contains both READ_CACHING and WRITE_CACHING:

            • For each RHOpContext ThisContext in Oplock.RHBreakQueue:

              • Call the algorithm in section 2.1.4.12.2, passing Open as the OperationOpen parameter, ThisContext.Open as the OplockOpen parameter, and Flags as the Flags parameter. If the algorithm returns FALSE:

                • Set ThisContext.BreakingToRead to FALSE.

                • If BreakCacheState contains HANDLE_CACHING:

                  • Set NeedToWait to TRUE.

                • EndIf

              • EndIf

            • EndFor

            • For each Open ThisOpen in Oplock.RHOplocks:

              • Call the algorithm in section 2.1.4.12.2, passing Open as the OperationOpen parameter, ThisOpen as the OplockOpen parameter, and Flags as the Flags parameter. If the algorithm returns FALSE:

                • Remove ThisOpen from Oplock.RHOplocks.

                • Notify the server of an oplock break according to the algorithm in section 2.1.5.18.3, setting the algorithm's parameters as follows:

                  • BreakingOplockOpen equal to ThisOpen.

                  • NewOplockLevel equal to LEVEL_NONE.

                  • AcknowledgeRequired equal to TRUE.

                  • OplockCompletionStatus equal to STATUS_SUCCESS.

                • (The operation does not end at this point; this call to 2.1.5.18.3 completes some earlier call to 2.1.5.18.2.)

                • Initialize a new RHOpContext object, setting its fields as follows:

                  • RHOpContext.Open set to ThisOpen.

                  • RHOpContext.BreakingToRead to FALSE.

                • Add the new RHOpContext object to Oplock.RHBreakQueue.

                • If BreakCacheState contains HANDLE_CACHING:

                  • Set NeedToWait to TRUE.

                • EndIf

              • EndIf

            • EndFor

          • EndIf

          • // If the oplock is explicitly losing HANDLE_CACHING, RHBreakQueue is not empty,

          • // and the algorithm has not yet decided to wait, this operation might have to wait if

          • // there is an oplock on RHBreakQueue with a non-matching key. This is done

          • // because even if this operation didn't cause a break of a currently-granted Read-

          • // Handle caching oplock, it might have done so had a currently-breaking oplock still

          • // been granted.

          • If (NeedToWait is FALSE) and

            (Oplock.RHBreakQueue is not empty) and

            (BreakCacheState contains HANDLE_CACHING):

            • For each RHOpContext ThisContex in Oplock.RHBreakQueue:

              • If ThisContext.Open.OplockKey does not equal Open.OplockKey:

                • Set NeedToWait to TRUE.

                • Break out of the For loop.

              • EndIf

            • EndFor

          • EndIf

          • Recompute Oplock.State according to the algorithm in section 2.1.4.13, passing Oplock as the ThisOplock parameter.

        • EndCase

        • Case (READ_CACHING|HANDLE_CACHING|BREAK_TO_READ_CACHING):

          • If BreakCacheState contains READ_CACHING:

            • For each RHOpContext ThisContext in Oplock.RHBreakQueue:

              • Call the algorithm in section 2.1.4.12.2, passing Open as the OperationOpen parameter, ThisContext.Open as the OplockOpen parameter, and Flags as the Flags parameter. If the algorithm returns FALSE:

                • Set ThisContext.BreakingToRead to FALSE.

              • EndIf

              • Recompute Oplock.State according to the algorithm in section 2.1.4.13, passing Oplock as the ThisOplock parameter.

            • EndFor

          • EndIf

          • If BreakCacheState contains HANDLE_CACHING:

            • For each RHOpContext ThisContext in Oplock.RHBreakQueue:

              • If ThisContext.Open.OplockKey does not equal Open.OplockKey:

                • Set NeedToWait to TRUE.

                • Break out of the For loop.

              • EndIf

            • EndFor

          • EndIf

        • EndCase

        • Case (READ_CACHING|HANDLE_CACHING|BREAK_TO_NO_CACHING):

          • If BreakCacheState contains HANDLE_CACHING:

            • For each RHOpContext ThisContext in Oplock.RHBreakQueue:

              • If ThisContext.Open.OplockKey does not equal Open.OplockKey:

                • Set NeedToWait to TRUE.

                • Break out of the For loop.

              • EndIf

            • EndFor

          • EndIf

        • EndCase

        • Case (READ_CACHING|WRITE_CACHING|EXCLUSIVE):

          • If BreakCacheState contains both READ_CACHING and WRITE_CACHING:

            • Notify the server of an oplock break according to the algorithm in section 2.1.5.18.3, setting the algorithm's parameters as follows:

              • BreakingOplockOpen equal to Oplock.ExclusiveOpen.

              • NewOplockLevel equal to LEVEL_NONE.

              • AcknowledgeRequired equal to TRUE.

              • OplockCompletionStatus equal to STATUS_SUCCESS.

            • (The operation does not end at this point; this call to 2.1.5.18.3 completes some earlier call to 2.1.5.18.1.)

            • Set Oplock.State to (READ_CACHING|WRITE_CACHING|EXCLUSIVE|BREAK_TO_NO_CACHING).

            • Set NeedToWait to TRUE.

          • Else If BreakCacheState contains WRITE_CACHING:

            • Notify the server of an oplock break according to the algorithm in section 2.1.5.18.3, setting the algorithm's parameters as follows:

              • BreakingOplockOpen equal to Oplock.ExclusiveOpen.

              • NewOplockLevel equal to READ_CACHING.

              • AcknowledgeRequired equal to TRUE.

              • OplockCompletionStatus equal to STATUS_SUCCESS.

            • (The operation does not end at this point; this call to 2.1.5.18.3 completes some earlier call to 2.1.5.18.1.)

            • Set Oplock.State to (READ_CACHING|WRITE_CACHING| EXCLUSIVE|BREAK_TO_READ_CACHING).

            • Set NeedToWait to TRUE.

          • EndIf

        • EndCase

        • Case (READ_CACHING|WRITE_CACHING|HANDLE_CACHING|EXCLUSIVE):

          • If BreakCacheState equals WRITE_CACHING:

            • Notify the server of an oplock break according to the algorithm in section 2.1.5.18.3, setting the algorithm's parameters as follows:

              • BreakingOplockOpen equal to Oplock.ExclusiveOpen.

              • NewOplockLevel equal to (READ_CACHING|HANDLE_CACHING).

              • AcknowledgeRequired equal to TRUE.

              • OplockCompletionStatus equal to STATUS_SUCCESS.

            • (The operation does not end at this point; this call to 2.1.5.18.3 completes some earlier call to 2.1.5.18.1.)

            • Set Oplock.State to (READ_CACHING|WRITE_CACHING|HANDLE_CACHING|EXCLUSIVE|BREAK_TO_READ_CACHING|BREAK_TO_HANDLE_CACHING).

            • Set NeedToWait to TRUE.

          • Else If BreakCacheState equals HANDLE_CACHING:

            • Notify the server of an oplock break according to the algorithm in section 2.1.5.18.3, setting the algorithm's parameters as follows:

              • BreakingOplockOpen equal to Oplock.ExclusiveOpen.

              • NewOplockLevel equal to (READ_CACHING|WRITE_CACHING).

              • AcknowledgeRequired equal to TRUE.

              • OplockCompletionStatus equal to STATUS_SUCCESS.

            • (The operation does not end at this point; this call to 2.1.5.18.3 completes some earlier call to 2.1.5.18.1.)

            • Set Oplock.State to (READ_CACHING|WRITE_CACHING|HANDLE_CACHING|EXCLUSIVE|BREAK_TO_READ_CACHING|BREAK_TO_WRITE_CACHING).

            • Set NeedToWait to TRUE.

          • Else If BreakCacheState contains both READ_CACHING and WRITE_CACHING:

            • Notify the server of an oplock break according to the algorithm in section 2.1.5.18.3, setting the algorithm's parameters as follows:

              • BreakingOplockOpen equal to Oplock.ExclusiveOpen.

              • NewOplockLevel equal to LEVEL_NONE.

              • AcknowledgeRequired equal to TRUE.

              • OplockCompletionStatus equal to STATUS_SUCCESS.

            • (The operation does not end at this point; this call to 2.1.5.18.3 completes some earlier call to 2.1.5.18.1.)

            • Set Oplock.State to (READ_CACHING|WRITE_CACHING|HANDLE_CACHING|EXCLUSIVE|BREAK_TO_NO_CACHING).

            • Set NeedToWait to TRUE.

          • EndIf

        • EndCase

        • Case (READ_CACHING|WRITE_CACHING|EXCLUSIVE|BREAK_TO_READ_CACHING):

          • If BreakCacheState contains READ_CACHING:

            • Set Oplock.State to (READ_CACHING|WRITE_CACHING|EXCLUSIVE|BREAK_TO_NO_CACHING).

          • EndIf

          • If BreakCacheState contains either READ_CACHING or WRITE_CACHING:

            • Set NeedToWait to TRUE.

          • EndIf

        • EndCase

        • Case (READ_CACHING|WRITE_CACHING|EXCLUSIVE|BREAK_TO_NO_CACHING):

          • If BreakCacheState contains either READ_CACHING or WRITE_CACHING:

            • Set NeedToWait to TRUE.

          • EndIf

        • EndCase

        • Case (READ_CACHING|WRITE_CACHING|HANDLE_CACHING|EXCLUSIVE|BREAK_TO_READ_CACHING|BREAK_TO_WRITE_CACHING):

          • If BreakCacheState == WRITE_CACHING:

            • Set Oplock.State to (READ_CACHING|WRITE_CACHING|HANDLE_CACHING|EXCLUSIVE|BREAK_TO_READ_CACHING).

          • Else If BreakCacheState contains both READ_CACHING and WRITE_CACHING:

            • Set Oplock.State to (READ_CACHING|WRITE_CACHING|HANDLE_CACHING|EXCLUSIVE|BREAK_TO_NO_CACHING).

          • EndIf

          • Set NeedToWait to TRUE.

        • EndCase

        • Case (READ_CACHING|WRITE_CACHING|HANDLE_CACHING|EXCLUSIVE|BREAK_TO_READ_CACHING|BREAK_TO_HANDLE_CACHING):

          • If BreakCacheState == HANDLE_CACHING:

            • Set Oplock.State to (READ_CACHING|WRITE_CACHING|HANDLE_CACHING|EXCLUSIVE|BREAK_TO_READ_CACHING).

          • Else If BreakCacheState contains READ_CACHING:

            • Set Oplock.State to (READ_CACHING|WRITE_CACHING|HANDLE_CACHING|EXCLUSIVE|BREAK_TO_NO_CACHING).

          • EndIf

          • Set NeedToWait to TRUE.

        • EndCase

        • Case (READ_CACHING|WRITE_CACHING|HANDLE_CACHING|EXCLUSIVE|BREAK_TO_READ_CACHING):

          • If BreakCacheState contains READ_CACHING, set Oplock.State to (READ_CACHING|WRITE_CACHING|HANDLE_CACHING|EXCLUSIVE|BREAK_TO_NO_CACHING).

          • Set NeedToWait to TRUE.

        • EndCase

        • Case (READ_CACHING|WRITE_CACHING|HANDLE_CACHING|EXCLUSIVE|BREAK_TO_NO_CACHING):

          • Set NeedToWait to TRUE.

        • EndCase

      • EndSwitch

      • If NeedToWait is TRUE:

        • The operation that called this algorithm MUST be made cancelable by inserting it into CancelableOperations.CancelableOperationList.

        • Insert Open into Oplock.WaitList.

        • The operation that called this algorithm waits until the oplock break is acknowledged, as specified in section 2.1.5.19, or the operation is canceled.

      • EndIf

    • EndIf

  • EndIf

EndIf