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