| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.ComIntegration
- {
- using System;
- using System.ServiceModel;
- using System.Transactions;
- using System.Diagnostics;
- using System.ServiceModel.Diagnostics;
- using System.Runtime.InteropServices;
- using SR = System.ServiceModel.SR;
- class TransactionProxyBuilder : IProxyCreator
- {
- ComProxy comProxy = null;
- TransactionProxy txProxy = null;
- private TransactionProxyBuilder(TransactionProxy proxy)
- {
- this.txProxy = proxy;
- }
- void IDisposable.Dispose()
- {
- }
- ComProxy IProxyCreator.CreateProxy(IntPtr outer, ref Guid riid)
- {
- if ((riid != typeof(ITransactionProxy).GUID))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidCastException(SR.GetString(SR.NoInterface, riid)));
- if (outer == IntPtr.Zero)
- {
- // transactions require failfasts to prevent corruption
- DiagnosticUtility.FailFast("OuterProxy cannot be null");
- }
- if (comProxy == null)
- {
- comProxy = ComProxy.Create(outer, txProxy, null);
- return comProxy;
- }
- else
- return comProxy.Clone();
- }
- bool IProxyCreator.SupportsErrorInfo(ref Guid riid)
- {
- if ((riid != typeof(ITransactionProxy).GUID))
- return false;
- else
- return true;
- }
- bool IProxyCreator.SupportsDispatch()
- {
- return false;
- }
- bool IProxyCreator.SupportsIntrinsics()
- {
- return false;
- }
- public static IntPtr CreateTransactionProxyTearOff(TransactionProxy txProxy)
- {
- IProxyCreator txProxyBuilder = new TransactionProxyBuilder(txProxy);
- IProxyManager proxyManager = new ProxyManager(txProxyBuilder);
- Guid iid = typeof(ITransactionProxy).GUID;
- return OuterProxyWrapper.CreateOuterProxyInstance(proxyManager, ref iid);
- }
- }
- class TransactionProxy : ITransactionProxy,
- IExtension<InstanceContext>
- {
- Transaction currentTransaction;
- VoterBallot currentVoter;
- object syncRoot;
- Guid appid;
- Guid clsid;
- int instanceID = 0;
- public TransactionProxy(Guid appid, Guid clsid)
- {
- this.syncRoot = new object();
- this.appid = appid;
- this.clsid = clsid;
- }
- public Transaction CurrentTransaction
- {
- get
- {
- return this.currentTransaction;
- }
- }
- public Guid AppId
- {
- get
- {
- return this.appid;
- }
- }
- public Guid Clsid
- {
- get
- {
- return this.clsid;
- }
- }
- public int InstanceID
- {
- get
- {
- return this.instanceID;
- }
- set
- {
- this.instanceID = value;
- }
- }
- public void SetTransaction(Transaction transaction)
- {
- lock (this.syncRoot)
- {
- if (transaction == null)
- {
- // transactions require failfasts to prevent corruption
- DiagnosticUtility.FailFast("Attempting to set transaction to NULL");
- }
- if (this.currentTransaction == null)
- {
- ProxyEnlistment enlistment;
- enlistment = new ProxyEnlistment(this, transaction);
- transaction.EnlistVolatile(enlistment, EnlistmentOptions.None);
- this.currentTransaction = transaction;
- if (this.currentVoter != null)
- {
- this.currentVoter.SetTransaction(this.currentTransaction);
- }
- }
- else if (this.currentTransaction != transaction)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.TransactionMismatch());
- }
- }
- }
- // IExtension<ServiceInstance>
- public void Attach(InstanceContext owner) { }
- public void Detach(InstanceContext owner) { }
- // ITransactionProxy
- public void Commit(Guid guid)
- {
- // transactions require failfasts to prevent corruption
- DiagnosticUtility.FailFast("Commit not supported: BYOT only!");
- }
- public void Abort()
- {
- if (this.currentTransaction != null)
- {
- this.currentTransaction.Rollback();
- }
- }
- public IDtcTransaction Promote()
- {
- EnsureTransaction();
- return TransactionInterop.GetDtcTransaction(
- this.currentTransaction);
- }
- public void CreateVoter(
- ITransactionVoterNotifyAsync2 voterNotification,
- IntPtr voterBallot)
- {
- if (IntPtr.Zero == voterBallot)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("voterBallot");
- lock (this.syncRoot)
- {
- if (this.currentVoter != null)
- {
- // transactions require failfasts to prevent corruption
- DiagnosticUtility.FailFast("Assumption: proxy only needs one voter");
- }
- VoterBallot voter = new VoterBallot(voterNotification, this);
- if (this.currentTransaction != null)
- {
- voter.SetTransaction(this.currentTransaction);
- }
- this.currentVoter = voter;
- IntPtr ppv = InterfaceHelper.GetInterfacePtrForObject(typeof(ITransactionVoterBallotAsync2).GUID, this.currentVoter);
- Marshal.WriteIntPtr(voterBallot, ppv);
- }
- }
- public DtcIsolationLevel GetIsolationLevel()
- {
- DtcIsolationLevel retVal;
- switch (this.currentTransaction.IsolationLevel)
- {
- case IsolationLevel.Serializable:
- retVal = DtcIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE;
- break;
- case IsolationLevel.RepeatableRead:
- retVal = DtcIsolationLevel.ISOLATIONLEVEL_REPEATABLEREAD;
- break;
- case IsolationLevel.ReadCommitted:
- retVal = DtcIsolationLevel.ISOLATIONLEVEL_READCOMMITTED;
- break;
- case IsolationLevel.ReadUncommitted:
- retVal = DtcIsolationLevel.ISOLATIONLEVEL_READUNCOMMITTED;
- break;
- default:
- retVal = DtcIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE;
- break;
- }
- return retVal;
- }
- public Guid GetIdentifier()
- {
- return this.currentTransaction.TransactionInformation.DistributedIdentifier;
- }
- // ITransactionProxy2
- public bool IsReusable()
- {
- return true;
- }
- void ClearTransaction(ProxyEnlistment enlistment)
- {
- lock (this.syncRoot)
- {
- if (this.currentTransaction == null)
- {
- // transactions require failfasts to prevent corruption
- DiagnosticUtility.FailFast("Clearing inactive TransactionProxy");
- }
- if (enlistment.Transaction != this.currentTransaction)
- {
- // transactions require failfasts to prevent corruption
- DiagnosticUtility.FailFast("Incorrectly working on multiple transactions");
- }
- this.currentTransaction = null;
- this.currentVoter = null;
- }
- }
- void EnsureTransaction()
- {
- lock (this.syncRoot)
- {
- if (this.currentTransaction == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new COMException(null, HR.CONTEXT_E_NOTRANSACTION));
- }
- }
- class ProxyEnlistment : IEnlistmentNotification
- {
- TransactionProxy proxy;
- Transaction transaction;
- public ProxyEnlistment(TransactionProxy proxy,
- Transaction transaction)
- {
- this.proxy = proxy;
- this.transaction = transaction;
- }
- public Transaction Transaction
- {
- get { return this.transaction; }
- }
- public void Prepare(PreparingEnlistment preparingEnlistment)
- {
- this.proxy.ClearTransaction(this);
- this.proxy = null;
- preparingEnlistment.Done();
- }
- public void Commit(Enlistment enlistment)
- {
- // transactions require failfasts to prevent corruption
- DiagnosticUtility.FailFast("Should have voted read only");
- }
- public void Rollback(Enlistment enlistment)
- {
- this.proxy.ClearTransaction(this);
- this.proxy = null;
- enlistment.Done();
- }
- public void InDoubt(Enlistment enlistment)
- {
- // transactions require failfasts to prevent corruption
- DiagnosticUtility.FailFast("Should have voted read only");
- }
- }
- class VoterBallot : ITransactionVoterBallotAsync2, IEnlistmentNotification
- {
- const int S_OK = 0;
- ITransactionVoterNotifyAsync2 notification;
- Transaction transaction;
- Enlistment enlistment;
- PreparingEnlistment preparingEnlistment;
- TransactionProxy proxy;
- public VoterBallot(ITransactionVoterNotifyAsync2 notification, TransactionProxy proxy)
- {
- this.notification = notification;
- this.proxy = proxy;
- }
- public void SetTransaction(Transaction transaction)
- {
- if (this.transaction != null)
- {
- // transactions require failfasts to prevent corruption
- DiagnosticUtility.FailFast("Already have a transaction in the ballot!");
- }
- this.transaction = transaction;
- this.enlistment = transaction.EnlistVolatile(
- this,
- EnlistmentOptions.None);
- }
- public void Prepare(PreparingEnlistment enlistment)
- {
- this.preparingEnlistment = enlistment;
- this.notification.VoteRequest();
- }
- public void Rollback(Enlistment enlistment)
- {
- enlistment.Done();
- this.notification.Aborted(0, false, 0, S_OK);
- ComPlusTxProxyTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationTxProxyTxAbortedByTM,
- SR.TraceCodeComIntegrationTxProxyTxAbortedByTM, proxy.AppId, proxy.Clsid, transaction.TransactionInformation.DistributedIdentifier, proxy.InstanceID);
- Marshal.ReleaseComObject(this.notification);
- this.notification = null;
- }
- public void Commit(Enlistment enlistment)
- {
- enlistment.Done();
- this.notification.Committed(false, 0, S_OK);
- ComPlusTxProxyTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationTxProxyTxCommitted,
- SR.TraceCodeComIntegrationTxProxyTxCommitted, proxy.AppId, proxy.Clsid, transaction.TransactionInformation.DistributedIdentifier, proxy.InstanceID);
- Marshal.ReleaseComObject(this.notification);
- this.notification = null;
- }
- public void InDoubt(Enlistment enlistment)
- {
- enlistment.Done();
- this.notification.InDoubt();
- Marshal.ReleaseComObject(this.notification);
- this.notification = null;
- }
- public void VoteRequestDone(int hr, int reason)
- {
- if (this.preparingEnlistment == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.NoVoteIssued)));
- }
- if (S_OK == hr)
- {
- this.preparingEnlistment.Prepared();
- }
- else
- {
- this.preparingEnlistment.ForceRollback();
- ComPlusTxProxyTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationTxProxyTxAbortedByContext,
- SR.TraceCodeComIntegrationTxProxyTxAbortedByContext, proxy.AppId, proxy.Clsid, transaction.TransactionInformation.DistributedIdentifier, proxy.InstanceID);
- }
- }
- }
- }
- }
|