internal void FaultBind(ref InstanceHandleReference reference, ref List <InstanceHandleReference> handlesPendingResolution, Exception reason) { Fx.Assert(reference != null, "Bind not in progress in FaultBind."); Fx.Assert(reference.InstanceHandle != null, "Reference already canceled in FaultBind."); Fx.Assert(object.ReferenceEquals(this, reference.InstanceHandle.Owner), "FaultBind called on the wrong owner for a handle."); lock (HandlesLock) { LockResolutionMarker marker = reference as LockResolutionMarker; if (marker != null && !marker.IsComplete) { try { // Nothing to do here - following the patterns of dealing with handlesPendingResolution and setting NotifyMarkerComplete in a finally. } finally { marker.Reason = reason ?? new OperationCanceledException(SRCore.HandleFreed); marker.NotifyMarkerComplete(false); if (handlesPendingResolution == null) { handlesPendingResolution = new List <InstanceHandleReference>(1); } handlesPendingResolution.Add(marker); } } } }
internal bool FinishBind(ref InstanceHandleReference reference, ref long instanceVersion, ref List <InstanceHandleReference> handlesPendingResolution) { Fx.Assert(reference != null, "Bind not in progress in FinishBind."); Fx.Assert(reference.InstanceHandle != null, "Reference already canceled in FinishBind."); Fx.Assert(object.ReferenceEquals(this, reference.InstanceHandle.Owner), "FinishBind called on the wrong owner for a handle."); Fx.Assert(reference is LockResolutionMarker, "Must have started reclaim in order to finish it."); lock (HandlesLock) { LockResolutionMarker marker = (LockResolutionMarker)reference; Fx.AssertAndThrow(marker.IsComplete, "Called FinishBind prematurely."); if (marker.NonConflicting) { instanceVersion = marker.InstanceVersion; return(true); } try { if (marker.Reason != null) { throw Fx.Exception.AsError(marker.Reason); } Fx.Assert(marker.ConflictingHandle != null, "Should either have a conflicting handle or a reason in the conflicting case."); marker.InstanceHandle.ConflictingHandle = marker.ConflictingHandle; return(false); } finally { CancelReference(ref reference, ref handlesPendingResolution); } } }
internal bool FinishBind(ref InstanceHandleReference reference, ref long instanceVersion, ref List <InstanceHandleReference> handlesPendingResolution) { bool flag2; lock (this.HandlesLock) { LockResolutionMarker marker = (LockResolutionMarker)reference; Fx.AssertAndThrow(marker.IsComplete, "Called FinishBind prematurely."); if (marker.NonConflicting) { instanceVersion = marker.InstanceVersion; flag2 = true; } else { try { if (marker.Reason != null) { throw Fx.Exception.AsError(marker.Reason); } marker.InstanceHandle.ConflictingHandle = marker.ConflictingHandle; flag2 = false; } finally { this.CancelReference(ref reference, ref handlesPendingResolution); } } } return(flag2); }
internal static void ResolveHandles(List <InstanceHandleReference> handlesPendingResolution) { if (handlesPendingResolution != null) { foreach (InstanceHandleReference reference in handlesPendingResolution) { LockResolutionMarker marker = reference as LockResolutionMarker; marker.MarkerWaitHandle.Set(); } } }
internal AsyncWaitHandle InitiateLockResolution(long instanceVersion, ref InstanceHandleReference reference, ref List <InstanceHandleReference> handlesPendingResolution) { AsyncWaitHandle markerWaitHandle; Fx.AssertAndThrow(!(reference is LockResolutionMarker), "InitiateLockResolution already called."); lock (this.HandlesLock) { InstanceHandleReference reference2 = reference; LockResolutionMarker handleRef = null; try { InstanceHandle handle; if (this.BoundHandles.TryGetValue(reference.InstanceHandle.Id, out handle)) { Fx.AssertAndFailFast(!object.ReferenceEquals(handle, reference.InstanceHandle), "InstanceStore lock state is not correct in InitiateLockResolution."); if ((handle.Version <= 0L) || (instanceVersion <= 0L)) { if ((handle.Version != 0L) || (instanceVersion != 0L)) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InvalidLockToken)); } reference.InstanceHandle.ConflictingHandle = handle; return(null); } if (handle.Version >= instanceVersion) { reference.InstanceHandle.ConflictingHandle = handle; return(null); } } handleRef = new LockResolutionMarker(reference.InstanceHandle, instanceVersion); this.EnqueueReference(handleRef); reference = handleRef; markerWaitHandle = handleRef.MarkerWaitHandle; } finally { if (!object.ReferenceEquals(handleRef, reference)) { this.CancelReference(ref reference, ref handlesPendingResolution); if (handleRef != null) { reference2 = handleRef; this.CancelReference(ref reference2, ref handlesPendingResolution); } } else { this.CancelReference(ref reference2, ref handlesPendingResolution); } } } return(markerWaitHandle); }
// Must be called ouside InstanceHandle.ThisLock and HandlesLock. internal static void ResolveHandles(List <InstanceHandleReference> handlesPendingResolution) { if (handlesPendingResolution != null) { foreach (InstanceHandleReference handleRef in handlesPendingResolution) { LockResolutionMarker marker = handleRef as LockResolutionMarker; Fx.Assert(marker != null, "How did a non-marker get in here."); marker.MarkerWaitHandle.Set(); } } }
// Must be called with HandlesLock held. // This is called when a reference becomes the oldest in-progress reference for an instance. This triggers the end of resolution for markers. // Returns false if the resolution failed, meaning that the marker can be removed. bool CheckOldestReference(InstanceHandleReference handleRef, ref List <InstanceHandleReference> handlesPendingResolution) { LockResolutionMarker marker = handleRef as LockResolutionMarker; if (marker == null || marker.IsComplete) { return(true); } bool returnValue = true; try { InstanceHandle existingHandle; if (BoundHandles.TryGetValue(marker.InstanceHandle.Id, out existingHandle)) { Fx.AssertAndFailFast(!object.ReferenceEquals(existingHandle, marker.InstanceHandle), "InstanceStore lock state is not correct in CheckOldestReference."); if (existingHandle.Version <= 0 || marker.InstanceVersion <= 0) { if (existingHandle.Version != 0 || marker.InstanceVersion != 0) { marker.Reason = new InvalidOperationException(SRCore.InvalidLockToken); returnValue = false; } else { marker.ConflictingHandle = existingHandle; returnValue = false; } } else if (existingHandle.Version >= marker.InstanceVersion) { marker.ConflictingHandle = existingHandle; returnValue = false; } } // No other handles have committed a bind to this or a higher version! We are ok to do so, but it is still not committed, so we stay in queue. return(returnValue); } finally { marker.NotifyMarkerComplete(returnValue); if (handlesPendingResolution == null) { handlesPendingResolution = new List <InstanceHandleReference>(1); } handlesPendingResolution.Add(marker); } }
// Must be called with HandlesLock held. void CancelReference(ref InstanceHandleReference reference, ref List <InstanceHandleReference> handlesPendingResolution) { Guid wasBoundToInstanceId = reference.InstanceHandle.Id; try { LockResolutionMarker marker = reference as LockResolutionMarker; if (marker != null && !marker.IsComplete) { if (handlesPendingResolution == null) { handlesPendingResolution = new List <InstanceHandleReference>(1); } handlesPendingResolution.Add(marker); } } finally { reference.Cancel(); reference = null; } ProcessInProgressHandles(ref handlesPendingResolution); if (wasBoundToInstanceId != Guid.Empty) { Queue <InstanceHandleReference> instanceQueue; if (InProgressHandlesPerInstance.TryGetValue(wasBoundToInstanceId, out instanceQueue)) { while (instanceQueue.Count > 0) { InstanceHandleReference handleRef = instanceQueue.Peek(); if (handleRef.InstanceHandle != null) { if (CheckOldestReference(handleRef, ref handlesPendingResolution)) { break; } } instanceQueue.Dequeue(); } if (instanceQueue.Count == 0) { InProgressHandlesPerInstance.Remove(wasBoundToInstanceId); } } } }
private bool CheckOldestReference(InstanceHandleReference handleRef, ref List <InstanceHandleReference> handlesPendingResolution) { bool flag2; LockResolutionMarker item = handleRef as LockResolutionMarker; if ((item == null) || item.IsComplete) { return(true); } bool success = true; try { InstanceHandle handle; if (this.BoundHandles.TryGetValue(item.InstanceHandle.Id, out handle)) { Fx.AssertAndFailFast(!object.ReferenceEquals(handle, item.InstanceHandle), "InstanceStore lock state is not correct in CheckOldestReference."); if ((handle.Version <= 0L) || (item.InstanceVersion <= 0L)) { if ((handle.Version != 0L) || (item.InstanceVersion != 0L)) { item.Reason = new InvalidOperationException(SRCore.InvalidLockToken); success = false; } else { item.ConflictingHandle = handle; success = false; } } else if (handle.Version >= item.InstanceVersion) { item.ConflictingHandle = handle; success = false; } } flag2 = success; } finally { item.NotifyMarkerComplete(success); if (handlesPendingResolution == null) { handlesPendingResolution = new List <InstanceHandleReference>(1); } handlesPendingResolution.Add(item); } return(flag2); }
private void CancelReference(ref InstanceHandleReference reference, ref List <InstanceHandleReference> handlesPendingResolution) { Queue <InstanceHandleReference> queue; Guid id = reference.InstanceHandle.Id; try { LockResolutionMarker item = reference as LockResolutionMarker; if ((item != null) && !item.IsComplete) { if (handlesPendingResolution == null) { handlesPendingResolution = new List <InstanceHandleReference>(1); } handlesPendingResolution.Add(item); } } finally { reference.Cancel(); reference = null; } this.ProcessInProgressHandles(ref handlesPendingResolution); if ((id != Guid.Empty) && this.InProgressHandlesPerInstance.TryGetValue(id, out queue)) { while (queue.Count > 0) { InstanceHandleReference handleRef = queue.Peek(); if ((handleRef.InstanceHandle != null) && this.CheckOldestReference(handleRef, ref handlesPendingResolution)) { break; } queue.Dequeue(); } if (queue.Count == 0) { this.InProgressHandlesPerInstance.Remove(id); } } }
internal void FaultBind(ref InstanceHandleReference reference, ref List <InstanceHandleReference> handlesPendingResolution, Exception reason) { lock (this.HandlesLock) { LockResolutionMarker item = reference as LockResolutionMarker; if ((item != null) && !item.IsComplete) { try { } finally { item.Reason = reason ?? new OperationCanceledException(SRCore.HandleFreed); item.NotifyMarkerComplete(false); if (handlesPendingResolution == null) { handlesPendingResolution = new List <InstanceHandleReference>(1); } handlesPendingResolution.Add(item); } } } }
// This is called if we found an existing lock. This handle doesn't own the lock, but it could claim it, if it can prove // that no other live handle owns it. If this returns non-null, the outcome will be available later on the // InstanceHandleReference once the AsyncWaitHandle completes. (Null indicates a conflict with another handle.) // // The instanceVersion reported here was read under the transaction, but not changed. Either it was already committed, or it was written under // this transaction in a prior command on a different handle. Due to the latter case, we treat it as dirty - we do not publish it or take // any visible action (such as dooming handles) based on its value. internal AsyncWaitHandle InitiateLockResolution(long instanceVersion, ref InstanceHandleReference reference, ref List <InstanceHandleReference> handlesPendingResolution) { Fx.Assert(reference != null, "Bind wasn't registered - RegisterStartBind must be called."); Fx.Assert(reference.InstanceHandle != null, "Cannot cancel and complete a bind."); Fx.Assert(reference.InstanceHandle.Id != Guid.Empty, "Must be bound to an instance already."); Fx.AssertAndThrow(!(reference is LockResolutionMarker), "InitiateLockResolution already called."); lock (HandlesLock) { InstanceHandleReference cancelReference = reference; LockResolutionMarker markerReference = null; try { InstanceHandle existingHandle; if (BoundHandles.TryGetValue(reference.InstanceHandle.Id, out existingHandle)) { Fx.AssertAndFailFast(!object.ReferenceEquals(existingHandle, reference.InstanceHandle), "InstanceStore lock state is not correct in InitiateLockResolution."); if (existingHandle.Version <= 0 || instanceVersion <= 0) { if (existingHandle.Version != 0 || instanceVersion != 0) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InvalidLockToken)); } reference.InstanceHandle.ConflictingHandle = existingHandle; return(null); } if (existingHandle.Version >= instanceVersion) { reference.InstanceHandle.ConflictingHandle = existingHandle; return(null); } } // Put a marker in the InProgressHandles. If it makes it through, and there's still no conflicting handle, // then the lock can be claimed at this version. Only currently in-progress bindings have a chance of // staking a stronger claim to the lock version (if the store actually acquired the lock for the handle). markerReference = new LockResolutionMarker(reference.InstanceHandle, instanceVersion); EnqueueReference(markerReference); reference = markerReference; Fx.Assert(markerReference.MarkerWaitHandle != null, "Null MarkerWaitHandle?"); return(markerReference.MarkerWaitHandle); } finally { if (!object.ReferenceEquals(markerReference, reference)) { CancelReference(ref reference, ref handlesPendingResolution); if (markerReference != null) { cancelReference = markerReference; CancelReference(ref cancelReference, ref handlesPendingResolution); } } else { CancelReference(ref cancelReference, ref handlesPendingResolution); } } } }
// This is called if we found an existing lock. This handle doesn't own the lock, but it could claim it, if it can prove // that no other live handle owns it. If this returns non-null, the outcome will be available later on the // InstanceHandleReference once the AsyncWaitHandle completes. (Null indicates a conflict with another handle.) // // The instanceVersion reported here was read under the transaction, but not changed. Either it was already committed, or it was written under // this transaction in a prior command on a different handle. Due to the latter case, we treat it as dirty - we do not publish it or take // any visible action (such as dooming handles) based on its value. internal AsyncWaitHandle InitiateLockResolution(long instanceVersion, ref InstanceHandleReference reference, ref List<InstanceHandleReference> handlesPendingResolution) { Fx.Assert(reference != null, "Bind wasn't registered - RegisterStartBind must be called."); Fx.Assert(reference.InstanceHandle != null, "Cannot cancel and complete a bind."); Fx.Assert(reference.InstanceHandle.Id != Guid.Empty, "Must be bound to an instance already."); Fx.AssertAndThrow(!(reference is LockResolutionMarker), "InitiateLockResolution already called."); lock (HandlesLock) { InstanceHandleReference cancelReference = reference; LockResolutionMarker markerReference = null; try { InstanceHandle existingHandle; if (BoundHandles.TryGetValue(reference.InstanceHandle.Id, out existingHandle)) { Fx.AssertAndFailFast(!object.ReferenceEquals(existingHandle, reference.InstanceHandle), "InstanceStore lock state is not correct in InitiateLockResolution."); if (existingHandle.Version <= 0 || instanceVersion <= 0) { if (existingHandle.Version != 0 || instanceVersion != 0) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InvalidLockToken)); } reference.InstanceHandle.ConflictingHandle = existingHandle; return null; } if (existingHandle.Version >= instanceVersion) { reference.InstanceHandle.ConflictingHandle = existingHandle; return null; } } // Put a marker in the InProgressHandles. If it makes it through, and there's still no conflicting handle, // then the lock can be claimed at this version. Only currently in-progress bindings have a chance of // staking a stronger claim to the lock version (if the store actually acquired the lock for the handle). markerReference = new LockResolutionMarker(reference.InstanceHandle, instanceVersion); EnqueueReference(markerReference); reference = markerReference; Fx.Assert(markerReference.MarkerWaitHandle != null, "Null MarkerWaitHandle?"); return markerReference.MarkerWaitHandle; } finally { if (!object.ReferenceEquals(markerReference, reference)) { CancelReference(ref reference, ref handlesPendingResolution); if (markerReference != null) { cancelReference = markerReference; CancelReference(ref cancelReference, ref handlesPendingResolution); } } else { CancelReference(ref cancelReference, ref handlesPendingResolution); } } } }
internal AsyncWaitHandle InitiateLockResolution(long instanceVersion, ref InstanceHandleReference reference, ref List<InstanceHandleReference> handlesPendingResolution) { AsyncWaitHandle markerWaitHandle; Fx.AssertAndThrow(!(reference is LockResolutionMarker), "InitiateLockResolution already called."); lock (this.HandlesLock) { InstanceHandleReference reference2 = reference; LockResolutionMarker handleRef = null; try { InstanceHandle handle; if (this.BoundHandles.TryGetValue(reference.InstanceHandle.Id, out handle)) { Fx.AssertAndFailFast(!object.ReferenceEquals(handle, reference.InstanceHandle), "InstanceStore lock state is not correct in InitiateLockResolution."); if ((handle.Version <= 0L) || (instanceVersion <= 0L)) { if ((handle.Version != 0L) || (instanceVersion != 0L)) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InvalidLockToken)); } reference.InstanceHandle.ConflictingHandle = handle; return null; } if (handle.Version >= instanceVersion) { reference.InstanceHandle.ConflictingHandle = handle; return null; } } handleRef = new LockResolutionMarker(reference.InstanceHandle, instanceVersion); this.EnqueueReference(handleRef); reference = handleRef; markerWaitHandle = handleRef.MarkerWaitHandle; } finally { if (!object.ReferenceEquals(handleRef, reference)) { this.CancelReference(ref reference, ref handlesPendingResolution); if (handleRef != null) { reference2 = handleRef; this.CancelReference(ref reference2, ref handlesPendingResolution); } } else { this.CancelReference(ref reference2, ref handlesPendingResolution); } } } return markerWaitHandle; }