2.1.5.18.2 Algorithm to Request a Shared Oplock
The inputs for requesting a shared oplock are:
Open: The Open on which the oplock is being requested.
RequestedOplock: The oplock type being requested.
GrantingInAck: A Boolean value, TRUE if this oplock is being requested as part of an oplock break acknowledgement, FALSE if not.
On completion, the object store MUST return:
Status: An NTSTATUS code that specifies the result.
NewOplockLevel: The type of oplock that the requested oplock has been broken to. If a failure status is returned in Status, the value of this field is undefined. Valid values are as follows:
LEVEL_NONE (that is, no oplock)
LEVEL_TWO
A combination of one or more of the following flags:
READ_CACHING
HANDLE_CACHING
WRITE_CACHING
AcknowledgeRequired: A Boolean value: TRUE if the server MUST acknowledge the oplock break; FALSE if not, as specified in section 2.1.5.19. If a failure status is returned in Status, the value of this field is undefined.
The shared oplock request algorithm uses the following local variables:
Boolean value (initialized to FALSE): OplockGranted
Pseudocode for the algorithm is as follows:
If Open.Stream.Oplock is empty:
Build a new Oplock object with fields initialized as follows:
Oplock.State set to NO_OPLOCK.
All other fields set to 0/empty.
Store the new Oplock object in Open.Stream.Oplock.
EndIf
If (GrantingInAck is FALSE) and
(Open.Stream.Oplock.State contains one or more of BREAK_TO_TWO, BREAK_TO_NONE, BREAK_TO_TWO_TO_NONE, BREAK_TO_READ_CACHING, BREAK_TO_WRITE_CACHING, BREAK_TO_HANDLE_CACHING, BREAK_TO_NO_CACHING, or EXCLUSIVE), then:
The operation MUST be failed with Status set to STATUS_OPLOCK_NOT_GRANTED.
EndIf
Switch (RequestedOplock):
Case LEVEL_TWO:
The operation MUST be failed with Status set to STATUS_OPLOCK_NOT_GRANTED if Open.Stream.Oplock.State is anything other than the following:
NO_OPLOCK
LEVEL_TWO_OPLOCK
READ_CACHING
(LEVEL_TWO_OPLOCK|READ_CACHING)
// Deliberate FALL-THROUGH to next Case statement.
Case READ_CACHING:
The operation MUST be failed with Status set to STATUS_OPLOCK_NOT_GRANTED if GrantingInAck is FALSE and Open.Stream.Oplock.State is anything other than the following:
NO_OPLOCK
LEVEL_TWO_OPLOCK
READ_CACHING
(LEVEL_TWO_OPLOCK|READ_CACHING)
(READ_CACHING|HANDLE_CACHING)
(READ_CACHING|HANDLE_CACHING|MIXED_R_AND_RH)
(READ_CACHING|HANDLE_CACHING|BREAK_TO_READ_CACHING)
(READ_CACHING|HANDLE_CACHING|BREAK_TO_NO_CACHING)
If GrantingInAck is FALSE:
If there is an Open on Open.Stream.Oplock.RHOplocks whose TargetOplockKey is equal to Open.TargetOplockKey, the operation MUST be failed with Status set to STATUS_OPLOCK_NOT_GRANTED.
If there is an Open on Open.Stream.Oplock.RHBreakQueue whose TargetOplockKey is equal to Open.TargetOplockKey, the operation MUST be failed with Status set to STATUS_OPLOCK_NOT_GRANTED.
If there is an Open ThisOpen on Open.Stream.Oplock.ROplocks whose TargetOplockKey is equal to Open.TargetOplockKey (there is supposed to be at most one present):
Remove ThisOpen from Open.Stream.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 READ_CACHING.
AcknowledgeRequired equal to FALSE.
OplockCompletionStatus equal to STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE.
(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
EndIf
If RequestedOplock equals LEVEL_TWO:
Add Open to Open.Stream.Oplock.IIOplocks.
Else // RequestedOplock equals READ_CACHING:
Add Open to Open.Stream.Oplock.ROplocks.
EndIf
Recompute Open.Stream.Oplock.State according to the algorithm in section 2.1.4.13, passing Open.Stream.Oplock as the ThisOplock parameter.
Set OplockGranted to TRUE.
EndCase
Case (READ_CACHING|HANDLE_CACHING):
The operation MUST be failed with Status set to STATUS_OPLOCK_NOT_GRANTED if GrantingInAck is FALSE and Open.Stream.Oplock.State is anything other than the following:
NO_OPLOCK
READ_CACHING
(READ_CACHING|HANDLE_CACHING)
(READ_CACHING|HANDLE_CACHING|MIXED_R_AND_RH)
(READ_CACHING|HANDLE_CACHING|BREAK_TO_READ_CACHING)
(READ_CACHING|HANDLE_CACHING|BREAK_TO_NO_CACHING)
If Open.Stream.IsDeleted is TRUE, the operation MUST be failed with Status set to STATUS_OPLOCK_NOT_GRANTED.
If GrantingInAck is FALSE:
If there is an Open ThisOpen on Open.Stream.Oplock.ROplocks whose TargetOplockKey is equal to Open.TargetOplockKey (there is supposed to be at most one present):
Remove ThisOpen from Open.Stream.Oplocks.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 (READ_CACHING|HANDLE_CACHING).
AcknowledgeRequired equal to FALSE.
OplockCompletionStatus equal to STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE.
(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
If there is an Open ThisOpen on Open.Stream.Oplock.RHOplocks whose TargetOplockKey is equal to Open.TargetOplockKey (there is supposed to be at most one present):
Remove ThisOpen from Open.Stream.Oplocks.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|HANDLE_CACHING).
AcknowledgeRequired equal to FALSE.
OplockCompletionStatus equal to STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE.
(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
EndIf
Add Open to Open.Stream.Oplock.RHOplocks.
Recompute Open.Stream.Oplock.State according to the algorithm in section 2.1.4.13, passing Open.Stream.Oplock as the ThisOplock parameter.
Set OplockGranted to TRUE.
EndCase
// No other value of RequestedOplock is possible.
EndSwitch
If OplockGranted is TRUE:
This operation MUST be made cancelable by inserting it into CancelableOperations.CancelableOperationList.
The operation waits until the oplock is broken or canceled, as specified in section 2.1.5.18.3. When the operation specified in section 2.1.5.18.3 is called, its following input parameters are transferred to this routine and returned by it:
Status is set to OplockCompletionStatus from the operation specified in section 2.1.5.18.3.
NewOplockLevel is set to NewOplockLevel from the operation specified in section 2.1.5.18.3.
AcknowledgeRequired is set to AcknowledgeRequired from the operation specified in section 2.1.5.18.3.
EndIf