Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / System.Runtime.DurableInstancing / System / Runtime / DurableInstancing / InstancePersistenceContext.cs / 1305376 / InstancePersistenceContext.cs
//---------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //--------------------------------------------------------------- namespace System.Runtime.DurableInstancing { using System.Collections.Generic; using System.Runtime.Serialization; using System.Security; using System.Threading; using System.Transactions; using System.Xml.Linq; [Fx.Tag.XamlVisible(false)] public sealed class InstancePersistenceContext { readonly TimeSpan timeout; Transaction transaction; bool freezeTransaction; CommittableTransaction myTransaction; int cancellationHandlerCalled; internal InstancePersistenceContext(InstanceHandle handle, Transaction transaction) : this(handle) { Fx.Assert(transaction != null, "Null Transaction passed to InstancePersistenceContext."); // Let's take our own clone of the transaction. We need to do this because we might need to // create a TransactionScope using the transaction and in cases where we are dealing with a // transaction that is flowed into the workflow on a message, the DependentTransaction that the // dispatcher creates and sets to Transaction.Current may already be Completed by the time a // Save operation is done. And since TransactionScope creates a DependentTransaction, it won't // be able to. // We don't create another DependentClone because we are going to do a EnlistVolatile on the // transaction ourselves. this.transaction = transaction.Clone(); IsHostTransaction = true; } internal InstancePersistenceContext(InstanceHandle handle, TimeSpan timeout) : this(handle) { this.timeout = timeout; } InstancePersistenceContext(InstanceHandle handle) { Fx.Assert(handle != null, "Null handle passed to InstancePersistenceContext."); InstanceHandle = handle; // Fork a copy of the current view to be the new working view. It starts with no query results. InstanceView newView = handle.View.Clone(); newView.InstanceStoreQueryResults = null; InstanceView = newView; this.cancellationHandlerCalled = 0; } public InstanceHandle InstanceHandle { get; private set; } public InstanceView InstanceView { get; private set; } public long InstanceVersion { get { return InstanceHandle.Version; } } public Guid LockToken { get { Fx.Assert(InstanceHandle.Owner == null || InstanceHandle.Owner.OwnerToken == InstanceView.InstanceOwner.OwnerToken, "Mismatched lock tokens."); // If the handle doesn't own the lock yet, return the owner LockToken, which is needed to check whether this owner already owns locks. return InstanceHandle.Owner == null ? Guid.Empty : InstanceHandle.Owner.OwnerToken; } } public object UserContext { get { return InstanceHandle.ProviderObject; } } bool CancelRequested { get; set; } ExecuteAsyncResult RootAsyncResult { get; set; } ExecuteAsyncResult LastAsyncResult { get; set; } bool IsHostTransaction { get; set; } bool Active { get { return RootAsyncResult != null; } } public void SetCancellationHandler(ActioncancellationHandler) { ThrowIfNotActive("SetCancellationHandler"); LastAsyncResult.CancellationHandler = cancellationHandler; if (CancelRequested && (cancellationHandler != null)) { try { if (Interlocked.CompareExchange(ref this.cancellationHandlerCalled, 0, 1) == 0) { cancellationHandler(this); } } catch (Exception exception) { if (Fx.IsFatal(exception)) { throw; } throw Fx.Exception.AsError(new CallbackException(SRCore.OnCancelRequestedThrew, exception)); } } } public void BindInstanceOwner(Guid instanceOwnerId, Guid lockToken) { if (instanceOwnerId == Guid.Empty) { throw Fx.Exception.Argument("instanceOwnerId", SRCore.GuidCannotBeEmpty); } if (lockToken == Guid.Empty) { throw Fx.Exception.Argument("lockToken", SRCore.GuidCannotBeEmpty); } ThrowIfNotActive("BindInstanceOwner"); InstanceOwner owner = InstanceHandle.Store.GetOrCreateOwner(instanceOwnerId, lockToken); InstanceView.BindOwner(owner); IsHandleDoomedByRollback = true; InstanceHandle.BindOwner(owner); } public void BindInstance(Guid instanceId) { if (instanceId == Guid.Empty) { throw Fx.Exception.Argument("instanceId", SRCore.GuidCannotBeEmpty); } ThrowIfNotActive("BindInstance"); InstanceView.BindInstance(instanceId); IsHandleDoomedByRollback = true; InstanceHandle.BindInstance(instanceId); } public void BindEvent(InstancePersistenceEvent persistenceEvent) { if (persistenceEvent == null) { throw Fx.Exception.ArgumentNull("persistenceEvent"); } ThrowIfNotActive("BindEvent"); if (!InstanceView.IsBoundToInstanceOwner) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.ContextMustBeBoundToOwner)); } IsHandleDoomedByRollback = true; InstanceHandle.BindOwnerEvent(persistenceEvent); } public void BindAcquiredLock(long instanceVersion) { if (instanceVersion < 0) { throw Fx.Exception.ArgumentOutOfRange("instanceVersion", instanceVersion, SRCore.InvalidLockToken); } ThrowIfNotActive("BindAcquiredLock"); // This call has a synchronization, so we are guaranteed it is only successful once. InstanceView.BindLock(instanceVersion); IsHandleDoomedByRollback = true; InstanceHandle.Bind(instanceVersion); } public void BindReclaimedLock(long instanceVersion, TimeSpan timeout) { AsyncWaitHandle wait = InitiateBindReclaimedLockHelper("BindReclaimedLock", instanceVersion, timeout); if (!wait.Wait(timeout)) { InstanceHandle.CancelReclaim(new TimeoutException(SRCore.TimedOutWaitingForLockResolution)); } ConcludeBindReclaimedLockHelper(); } public IAsyncResult BeginBindReclaimedLock(long instanceVersion, TimeSpan timeout, AsyncCallback callback, object state) { AsyncWaitHandle wait = InitiateBindReclaimedLockHelper("BeginBindReclaimedLock", instanceVersion, timeout); return new BindReclaimedLockAsyncResult(this, wait, timeout, callback, state); } public void EndBindReclaimedLock(IAsyncResult result) { BindReclaimedLockAsyncResult.End(result); } public Exception CreateBindReclaimedLockException(long instanceVersion) { AsyncWaitHandle wait = InitiateBindReclaimedLockHelper("CreateBindReclaimedLockException", instanceVersion, TimeSpan.MaxValue); return new BindReclaimedLockException(wait); } AsyncWaitHandle InitiateBindReclaimedLockHelper(string methodName, long instanceVersion, TimeSpan timeout) { if (instanceVersion < 0) { throw Fx.Exception.ArgumentOutOfRange("instanceVersion", instanceVersion, SRCore.InvalidLockToken); } TimeoutHelper.ThrowIfNegativeArgument(timeout); ThrowIfNotActive(methodName); // This call has a synchronization, so we are guaranteed it is only successful once. InstanceView.StartBindLock(instanceVersion); IsHandleDoomedByRollback = true; AsyncWaitHandle wait = InstanceHandle.StartReclaim(instanceVersion); if (wait == null) { InstanceHandle.Free(); throw Fx.Exception.AsError(new InstanceHandleConflictException(LastAsyncResult.CurrentCommand.Name, InstanceView.InstanceId)); } return wait; } void ConcludeBindReclaimedLockHelper() { // If FinishReclaim doesn't throw an exception, we are done - the reclaim was successful. // The Try / Finally makes up for the reverse order of setting the handle, then the view. long instanceVersion = -1; try { if (!InstanceHandle.FinishReclaim(ref instanceVersion)) { InstanceHandle.Free(); throw Fx.Exception.AsError(new InstanceHandleConflictException(LastAsyncResult.CurrentCommand.Name, InstanceView.InstanceId)); } Fx.Assert(instanceVersion >= 0, "Where did the instance version go?"); } finally { if (instanceVersion >= 0) { InstanceView.FinishBindLock(instanceVersion); } } } public void PersistedInstance(IDictionary data) { ThrowIfNotLocked(); ThrowIfCompleted(); ThrowIfNotTransactional("PersistedInstance"); InstanceView.InstanceData = data.ReadOnlyCopy(true); InstanceView.InstanceDataConsistency = InstanceValueConsistency.None; InstanceView.InstanceState = InstanceState.Initialized; } public void LoadedInstance(InstanceState state, IDictionary instanceData, IDictionary instanceMetadata, IDictionary > associatedInstanceKeyMetadata, IDictionary > completedInstanceKeyMetadata) { if (state == InstanceState.Uninitialized) { if (instanceData != null && instanceData.Count > 0) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.UninitializedCannotHaveData)); } } else if (state == InstanceState.Completed) { if (associatedInstanceKeyMetadata != null && associatedInstanceKeyMetadata.Count > 0) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.CompletedMustNotHaveAssociatedKeys)); } } else if (state != InstanceState.Initialized) { throw Fx.Exception.Argument("state", SRCore.InvalidInstanceState); } ThrowIfNoInstance(); ThrowIfNotActive("PersistedInstance"); InstanceValueConsistency consistency = InstanceView.IsBoundToLock || state == InstanceState.Completed ? InstanceValueConsistency.None : InstanceValueConsistency.InDoubt; ReadOnlyDictionary instanceDataCopy = instanceData.ReadOnlyCopy(false); ReadOnlyDictionary instanceMetadataCopy = instanceMetadata.ReadOnlyCopy(false); Dictionary keysCopy = null; int totalKeys = (associatedInstanceKeyMetadata != null ? associatedInstanceKeyMetadata.Count : 0) + (completedInstanceKeyMetadata != null ? completedInstanceKeyMetadata.Count : 0); if (totalKeys > 0) { keysCopy = new Dictionary (totalKeys); } if (associatedInstanceKeyMetadata != null && associatedInstanceKeyMetadata.Count > 0) { foreach (KeyValuePair > keyMetadata in associatedInstanceKeyMetadata) { InstanceKeyView view = new InstanceKeyView(keyMetadata.Key); view.InstanceKeyState = InstanceKeyState.Associated; view.InstanceKeyMetadata = keyMetadata.Value.ReadOnlyCopy(false); view.InstanceKeyMetadataConsistency = InstanceView.IsBoundToLock ? InstanceValueConsistency.None : InstanceValueConsistency.InDoubt; keysCopy.Add(view.InstanceKey, view); } } if (completedInstanceKeyMetadata != null && completedInstanceKeyMetadata.Count > 0) { foreach (KeyValuePair > keyMetadata in completedInstanceKeyMetadata) { InstanceKeyView view = new InstanceKeyView(keyMetadata.Key); view.InstanceKeyState = InstanceKeyState.Completed; view.InstanceKeyMetadata = keyMetadata.Value.ReadOnlyCopy(false); view.InstanceKeyMetadataConsistency = consistency; keysCopy.Add(view.InstanceKey, view); } } InstanceView.InstanceState = state; InstanceView.InstanceData = instanceDataCopy; InstanceView.InstanceDataConsistency = consistency; InstanceView.InstanceMetadata = instanceMetadataCopy; InstanceView.InstanceMetadataConsistency = consistency; InstanceView.InstanceKeys = keysCopy == null ? null : new ReadOnlyDictionary (keysCopy, false); InstanceView.InstanceKeysConsistency = consistency; } public void CompletedInstance() { ThrowIfNotLocked(); ThrowIfUninitialized(); ThrowIfCompleted(); if ((InstanceView.InstanceKeysConsistency & InstanceValueConsistency.InDoubt) == 0) { foreach (KeyValuePair key in InstanceView.InstanceKeys) { if (key.Value.InstanceKeyState == InstanceKeyState.Associated) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.CannotCompleteWithKeys)); } } } ThrowIfNotTransactional("CompletedInstance"); InstanceView.InstanceState = InstanceState.Completed; } public void ReadInstanceMetadata(IDictionary metadata, bool complete) { ThrowIfNoInstance(); ThrowIfNotActive("ReadInstanceMetadata"); if (InstanceView.InstanceMetadataConsistency == InstanceValueConsistency.None) { return; } if (complete) { InstanceView.InstanceMetadata = metadata.ReadOnlyCopy(false); InstanceView.InstanceMetadataConsistency = InstanceView.IsBoundToLock || InstanceView.InstanceState == InstanceState.Completed ? InstanceValueConsistency.None : InstanceValueConsistency.InDoubt; } else { if ((InstanceView.IsBoundToLock || InstanceView.InstanceState == InstanceState.Completed) && (InstanceView.InstanceMetadataConsistency & InstanceValueConsistency.InDoubt) != 0) { // In this case, prefer throwing out old data and keeping only authoritative data. InstanceView.InstanceMetadata = metadata.ReadOnlyMergeInto(null, false); InstanceView.InstanceMetadataConsistency = InstanceValueConsistency.Partial; } else { InstanceView.InstanceMetadata = metadata.ReadOnlyMergeInto(InstanceView.InstanceMetadata, false); InstanceView.InstanceMetadataConsistency |= InstanceValueConsistency.Partial; } } } public void WroteInstanceMetadataValue(XName name, InstanceValue value) { if (name == null) { throw Fx.Exception.ArgumentNull("name"); } if (value == null) { throw Fx.Exception.ArgumentNull("value"); } ThrowIfNotLocked(); ThrowIfCompleted(); ThrowIfNotTransactional("WroteInstanceMetadataValue"); InstanceView.AccumulatedMetadataWrites[name] = value; } public void AssociatedInstanceKey(Guid key) { if (key == Guid.Empty) { throw Fx.Exception.Argument("key", SRCore.InvalidKeyArgument); } ThrowIfNotLocked(); ThrowIfCompleted(); ThrowIfNotTransactional("AssociatedInstanceKey"); Dictionary copy = new Dictionary (InstanceView.InstanceKeys); if ((InstanceView.InstanceKeysConsistency & InstanceValueConsistency.InDoubt) == 0 && copy.ContainsKey(key)) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.KeyAlreadyAssociated)); } InstanceKeyView keyView = new InstanceKeyView(key); keyView.InstanceKeyState = InstanceKeyState.Associated; keyView.InstanceKeyMetadataConsistency = InstanceValueConsistency.None; copy[keyView.InstanceKey] = keyView; InstanceView.InstanceKeys = new ReadOnlyDictionary (copy, false); } public void CompletedInstanceKey(Guid key) { if (key == Guid.Empty) { throw Fx.Exception.Argument("key", SRCore.InvalidKeyArgument); } ThrowIfNotLocked(); ThrowIfCompleted(); ThrowIfNotTransactional("CompletedInstanceKey"); InstanceKeyView existingKeyView; InstanceView.InstanceKeys.TryGetValue(key, out existingKeyView); if ((InstanceView.InstanceKeysConsistency & InstanceValueConsistency.InDoubt) == 0) { if (existingKeyView != null) { if (existingKeyView.InstanceKeyState == InstanceKeyState.Completed) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.KeyAlreadyCompleted)); } } else if ((InstanceView.InstanceKeysConsistency & InstanceValueConsistency.Partial) == 0) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.KeyNotAssociated)); } } if (existingKeyView != null) { existingKeyView.InstanceKeyState = InstanceKeyState.Completed; } else { Dictionary copy = new Dictionary (InstanceView.InstanceKeys); InstanceKeyView keyView = new InstanceKeyView(key); keyView.InstanceKeyState = InstanceKeyState.Completed; keyView.InstanceKeyMetadataConsistency = InstanceValueConsistency.Partial; copy[keyView.InstanceKey] = keyView; InstanceView.InstanceKeys = new ReadOnlyDictionary (copy, false); } } public void UnassociatedInstanceKey(Guid key) { if (key == Guid.Empty) { throw Fx.Exception.Argument("key", SRCore.InvalidKeyArgument); } ThrowIfNotLocked(); ThrowIfCompleted(); ThrowIfNotTransactional("UnassociatedInstanceKey"); InstanceKeyView existingKeyView; InstanceView.InstanceKeys.TryGetValue(key, out existingKeyView); if ((InstanceView.InstanceKeysConsistency & InstanceValueConsistency.InDoubt) == 0) { if (existingKeyView != null) { if (existingKeyView.InstanceKeyState == InstanceKeyState.Associated) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.KeyNotCompleted)); } } else if ((InstanceView.InstanceKeysConsistency & InstanceValueConsistency.Partial) == 0) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.KeyAlreadyUnassociated)); } } if (existingKeyView != null) { Dictionary copy = new Dictionary (InstanceView.InstanceKeys); copy.Remove(key); InstanceView.InstanceKeys = new ReadOnlyDictionary (copy, false); } } public void ReadInstanceKeyMetadata(Guid key, IDictionary metadata, bool complete) { if (key == Guid.Empty) { throw Fx.Exception.Argument("key", SRCore.InvalidKeyArgument); } ThrowIfNoInstance(); ThrowIfNotActive("ReadInstanceKeyMetadata"); InstanceKeyView keyView; if (!InstanceView.InstanceKeys.TryGetValue(key, out keyView)) { if (InstanceView.InstanceKeysConsistency == InstanceValueConsistency.None) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.KeyNotAssociated)); } Dictionary copy = new Dictionary (InstanceView.InstanceKeys); keyView = new InstanceKeyView(key); if (complete) { keyView.InstanceKeyMetadata = metadata.ReadOnlyCopy(false); keyView.InstanceKeyMetadataConsistency = InstanceValueConsistency.None; } else { keyView.InstanceKeyMetadata = metadata.ReadOnlyMergeInto(null, false); keyView.InstanceKeyMetadataConsistency = InstanceValueConsistency.Partial; } if (!InstanceView.IsBoundToLock && InstanceView.InstanceState != InstanceState.Completed) { keyView.InstanceKeyMetadataConsistency |= InstanceValueConsistency.InDoubt; } copy[keyView.InstanceKey] = keyView; InstanceView.InstanceKeys = new ReadOnlyDictionary (copy, false); } else { if (keyView.InstanceKeyMetadataConsistency == InstanceValueConsistency.None) { return; } if (complete) { keyView.InstanceKeyMetadata = metadata.ReadOnlyCopy(false); keyView.InstanceKeyMetadataConsistency = InstanceView.IsBoundToLock || InstanceView.InstanceState == InstanceState.Completed ? InstanceValueConsistency.None : InstanceValueConsistency.InDoubt; } else { if ((InstanceView.IsBoundToLock || InstanceView.InstanceState == InstanceState.Completed) && (keyView.InstanceKeyMetadataConsistency & InstanceValueConsistency.InDoubt) != 0) { // In this case, prefer throwing out old data and keeping only authoritative data. keyView.InstanceKeyMetadata = metadata.ReadOnlyMergeInto(null, false); keyView.InstanceKeyMetadataConsistency = InstanceValueConsistency.Partial; } else { keyView.InstanceKeyMetadata = metadata.ReadOnlyMergeInto(keyView.InstanceKeyMetadata, false); keyView.InstanceKeyMetadataConsistency |= InstanceValueConsistency.Partial; } } } } public void WroteInstanceKeyMetadataValue(Guid key, XName name, InstanceValue value) { if (key == Guid.Empty) { throw Fx.Exception.Argument("key", SRCore.InvalidKeyArgument); } if (name == null) { throw Fx.Exception.ArgumentNull("name"); } if (value == null) { throw Fx.Exception.ArgumentNull("value"); } ThrowIfNotLocked(); ThrowIfCompleted(); ThrowIfNotTransactional("WroteInstanceKeyMetadataValue"); InstanceKeyView keyView; if (!InstanceView.InstanceKeys.TryGetValue(key, out keyView)) { if (InstanceView.InstanceKeysConsistency == InstanceValueConsistency.None) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.KeyNotAssociated)); } if (!value.IsWriteOnly() && !value.IsDeletedValue) { Dictionary copy = new Dictionary (InstanceView.InstanceKeys); keyView = new InstanceKeyView(key); keyView.AccumulatedMetadataWrites.Add(name, value); keyView.InstanceKeyMetadataConsistency = InstanceValueConsistency.Partial; copy[keyView.InstanceKey] = keyView; InstanceView.InstanceKeys = new ReadOnlyDictionary (copy, false); InstanceView.InstanceKeysConsistency |= InstanceValueConsistency.Partial; } } else { keyView.AccumulatedMetadataWrites.Add(name, value); } } public void ReadInstanceOwnerMetadata(IDictionary metadata, bool complete) { ThrowIfNoOwner(); ThrowIfNotActive("ReadInstanceOwnerMetadata"); if (InstanceView.InstanceOwnerMetadataConsistency == InstanceValueConsistency.None) { return; } if (complete) { InstanceView.InstanceOwnerMetadata = metadata.ReadOnlyCopy(false); InstanceView.InstanceOwnerMetadataConsistency = InstanceValueConsistency.InDoubt; } else { InstanceView.InstanceOwnerMetadata = metadata.ReadOnlyMergeInto(InstanceView.InstanceOwnerMetadata, false); InstanceView.InstanceOwnerMetadataConsistency |= InstanceValueConsistency.Partial; } } public void WroteInstanceOwnerMetadataValue(XName name, InstanceValue value) { if (name == null) { throw Fx.Exception.ArgumentNull("name"); } if (value == null) { throw Fx.Exception.ArgumentNull("value"); } ThrowIfNoOwner(); ThrowIfNotTransactional("WroteInstanceOwnerMetadataValue"); InstanceView.AccumulatedOwnerMetadataWrites.Add(name, value); } public void QueriedInstanceStore(InstanceStoreQueryResult queryResult) { if (queryResult == null) { throw Fx.Exception.ArgumentNull("queryResult"); } ThrowIfNotActive("QueriedInstanceStore"); InstanceView.QueryResultsBacking.Add(queryResult); } [Fx.Tag.Throws.Timeout("The operation timed out.")] [Fx.Tag.Throws(typeof(OperationCanceledException), "The operation was canceled because the InstanceHandle has been freed.")] [Fx.Tag.Throws(typeof(InstancePersistenceException), "A command failed.")] [Fx.Tag.Blocking(CancelMethod = "NotifyHandleFree")] public void Execute(InstancePersistenceCommand command, TimeSpan timeout) { if (command == null) { throw Fx.Exception.ArgumentNull("command"); } ThrowIfNotActive("Execute"); try { ReconcileTransaction(); ExecuteAsyncResult.End(new ExecuteAsyncResult(this, command, timeout)); } catch (TimeoutException) { InstanceHandle.Free(); throw; } catch (OperationCanceledException) { InstanceHandle.Free(); throw; } } // For each level of hierarchy of command execution, only one BeginExecute may be pending at a time. [Fx.Tag.InheritThrows(From = "Execute")] public IAsyncResult BeginExecute(InstancePersistenceCommand command, TimeSpan timeout, AsyncCallback callback, object state) { if (command == null) { throw Fx.Exception.ArgumentNull("command"); } ThrowIfNotActive("BeginExecute"); try { ReconcileTransaction(); return new ExecuteAsyncResult(this, command, timeout, callback, state); } catch (TimeoutException) { InstanceHandle.Free(); throw; } catch (OperationCanceledException) { InstanceHandle.Free(); throw; } } [Fx.Tag.InheritThrows(From = "Execute")] [Fx.Tag.Blocking(CancelMethod = "NotifyHandleFree", Conditional = "!result.IsCompleted")] public void EndExecute(IAsyncResult result) { ExecuteAsyncResult.End(result); } internal Transaction Transaction { get { return this.transaction; } } internal bool IsHandleDoomedByRollback { get; private set; } internal void RequireTransaction() { if (this.transaction != null) { return; } Fx.AssertAndThrow(!this.freezeTransaction, "RequireTransaction called when transaction is frozen."); Fx.AssertAndThrow(Active, "RequireTransaction called when no command is active."); // It's ok if some time has passed since the timeout value was acquired, it is ok to run long. This transaction is not generally responsible // for timing out the Execute operation. The exception to this rule is during Commit. this.myTransaction = new CommittableTransaction(new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted, Timeout = this.timeout }); Transaction clone = this.myTransaction.Clone(); RootAsyncResult.SetInteriorTransaction(this.myTransaction, true); this.transaction = clone; } internal void PrepareForReuse() { Fx.AssertAndThrow(!Active, "Prior use not yet complete!"); Fx.AssertAndThrow(IsHostTransaction, "Can only reuse contexts with host transactions."); } internal void NotifyHandleFree() { CancelRequested = true; ExecuteAsyncResult lastAsyncResult = LastAsyncResult; Action onCancel = lastAsyncResult == null ? null : lastAsyncResult.CancellationHandler; if (onCancel != null) { try { if (Interlocked.CompareExchange(ref this.cancellationHandlerCalled, 0, 1) == 0) { onCancel(this); } } catch (Exception exception) { if (Fx.IsFatal(exception)) { throw; } throw Fx.Exception.AsError(new CallbackException(SRCore.OnCancelRequestedThrew, exception)); } } } [Fx.Tag.Blocking(CancelMethod = "NotifyHandleFree")] internal static InstanceView OuterExecute(InstanceHandle initialInstanceHandle, InstancePersistenceCommand command, Transaction transaction, TimeSpan timeout) { try { return ExecuteAsyncResult.End(new ExecuteAsyncResult(initialInstanceHandle, command, transaction, timeout)); } catch (TimeoutException) { initialInstanceHandle.Free(); throw; } catch (OperationCanceledException) { initialInstanceHandle.Free(); throw; } } internal static IAsyncResult BeginOuterExecute(InstanceHandle initialInstanceHandle, InstancePersistenceCommand command, Transaction transaction, TimeSpan timeout, AsyncCallback callback, object state) { try { return new ExecuteAsyncResult(initialInstanceHandle, command, transaction, timeout, callback, state); } catch (TimeoutException) { initialInstanceHandle.Free(); throw; } catch (OperationCanceledException) { initialInstanceHandle.Free(); throw; } } [Fx.Tag.Blocking(CancelMethod = "NotifyHandleFree", Conditional = "!result.IsCompleted")] internal static InstanceView EndOuterExecute(IAsyncResult result) { InstanceView finalState = ExecuteAsyncResult.End(result); if (finalState == null) { throw Fx.Exception.Argument("result", SRCore.InvalidAsyncResult); } return finalState; } void ThrowIfNotLocked() { if (!InstanceView.IsBoundToLock) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InstanceOperationRequiresLock)); } } void ThrowIfNoInstance() { if (!InstanceView.IsBoundToInstance) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InstanceOperationRequiresInstance)); } } void ThrowIfNoOwner() { if (!InstanceView.IsBoundToInstanceOwner) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InstanceOperationRequiresOwner)); } } void ThrowIfCompleted() { if (InstanceView.IsBoundToLock && InstanceView.InstanceState == InstanceState.Completed) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InstanceOperationRequiresNotCompleted)); } } void ThrowIfUninitialized() { if (InstanceView.IsBoundToLock && InstanceView.InstanceState == InstanceState.Uninitialized) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InstanceOperationRequiresNotUninitialized)); } } void ThrowIfNotActive(string methodName) { if (!Active) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.OutsideInstanceExecutionScope(methodName))); } } void ThrowIfNotTransactional(string methodName) { ThrowIfNotActive(methodName); if (RootAsyncResult.CurrentCommand.IsTransactionEnlistmentOptional) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.OutsideTransactionalCommand(methodName))); } } void ReconcileTransaction() { // If the provider fails to flow the transaction, that's fine, we don't consider that a request // not to use one. Transaction transaction = Transaction.Current; if (transaction != null) { if (this.transaction == null) { if (this.freezeTransaction) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.MustSetTransactionOnFirstCall)); } RootAsyncResult.SetInteriorTransaction(transaction, false); this.transaction = transaction; } else if (!transaction.Equals(this.transaction)) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.CannotReplaceTransaction)); } } this.freezeTransaction = true; } class ExecuteAsyncResult : AsyncResult, ISinglePhaseNotification { static AsyncCompletion onAcquireContext = new AsyncCompletion(OnAcquireContext); static AsyncCompletion onTryCommand = new AsyncCompletion(OnTryCommand); static AsyncCompletion onCommit = new AsyncCompletion(OnCommit); static Action
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- QueuePropertyVariants.cs
- OleDbInfoMessageEvent.cs
- SynchronizationLockException.cs
- Rotation3D.cs
- SystemTcpStatistics.cs
- SqlTypesSchemaImporter.cs
- XomlCompiler.cs
- ImageCollectionCodeDomSerializer.cs
- PenContexts.cs
- LicFileLicenseProvider.cs
- SafeEventLogWriteHandle.cs
- RegexCode.cs
- IList.cs
- XmlObjectSerializerWriteContextComplexJson.cs
- _SslStream.cs
- TransformedBitmap.cs
- XamlBrushSerializer.cs
- InProcStateClientManager.cs
- SystemIPv4InterfaceProperties.cs
- LinqToSqlWrapper.cs
- AddInIpcChannel.cs
- ThemeInfoAttribute.cs
- RefExpr.cs
- XmlObjectSerializerReadContextComplex.cs
- XmlDigitalSignatureProcessor.cs
- TextTreeNode.cs
- EventLogPermissionEntry.cs
- XPathDocumentNavigator.cs
- DrawingAttributesDefaultValueFactory.cs
- WebPermission.cs
- Set.cs
- DoubleAnimationClockResource.cs
- DataSvcMapFileSerializer.cs
- WhitespaceRuleLookup.cs
- RawStylusActions.cs
- DetailsViewInsertEventArgs.cs
- Context.cs
- TextBoxAutoCompleteSourceConverter.cs
- Brush.cs
- DoubleStorage.cs
- ClickablePoint.cs
- CodeParameterDeclarationExpression.cs
- OrCondition.cs
- CryptoApi.cs
- WindowsFormsSectionHandler.cs
- GeometryDrawing.cs
- CardSpaceSelector.cs
- PropagatorResult.cs
- StatusBarItem.cs
- VisualTreeHelper.cs
- OwnerDrawPropertyBag.cs
- SQLInt64.cs
- DataServiceHostFactory.cs
- IPCCacheManager.cs
- InfiniteIntConverter.cs
- StatusBarPanelClickEvent.cs
- SiteMapHierarchicalDataSourceView.cs
- RectAnimation.cs
- PolicyStatement.cs
- DesignerHost.cs
- TemplateBindingExtensionConverter.cs
- RootDesignerSerializerAttribute.cs
- SerialPinChanges.cs
- HyperLink.cs
- WebPart.cs
- PrinterSettings.cs
- SecurityElement.cs
- WebPartsPersonalization.cs
- SoapMessage.cs
- DataGridViewBand.cs
- WebConfigurationHost.cs
- Pens.cs
- LogReserveAndAppendState.cs
- PropertyItem.cs
- WebPartDescription.cs
- DesignerProperties.cs
- TransformerTypeCollection.cs
- ToolStripOverflowButton.cs
- EdmSchemaError.cs
- StringPropertyBuilder.cs
- WebControlsSection.cs
- SqlGenericUtil.cs
- XmlSerializerSection.cs
- BitStack.cs
- InvalidDocumentContentsException.cs
- LoginAutoFormat.cs
- BindableTemplateBuilder.cs
- SerializationSectionGroup.cs
- SplineQuaternionKeyFrame.cs
- OptimalTextSource.cs
- ProviderConnectionPoint.cs
- FixedTextContainer.cs
- Part.cs
- CacheModeValueSerializer.cs
- CodeValidator.cs
- SchemaImporter.cs
- TimeSpanValidatorAttribute.cs
- PathGeometry.cs
- DocumentsTrace.cs
- AutomationPropertyInfo.cs