Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Transactions / WsatProxy.cs / 1 / WsatProxy.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.ServiceModel.Transactions { using System; using System.ServiceModel.Channels; using System.Diagnostics; using System.Runtime.InteropServices; using System.ServiceModel; using System.Text; using System.Threading; using System.Transactions; using System.ServiceModel.Security; using System.ServiceModel.Diagnostics; using Microsoft.Transactions.Bridge; using Microsoft.Transactions.Wsat.Messaging; using Microsoft.Transactions.Wsat.Protocol; using DiagnosticUtility = System.ServiceModel.DiagnosticUtility; class WsatProxy { WsatConfiguration wsatConfig; ProtocolVersion protocolVersion; CoordinationService coordinationService; ActivationProxy activationProxy; object proxyLock = new object(); public WsatProxy(WsatConfiguration wsatConfig, ProtocolVersion protocolVersion) { this.wsatConfig = wsatConfig; this.protocolVersion = protocolVersion; } //============================================================================================= public Transaction UnmarshalTransaction(WsatTransactionInfo info) { if(info.Context.ProtocolVersion != this.protocolVersion) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new ArgumentException(SR.GetString(SR.InvalidWsatProtocolVersion))); } if (wsatConfig.OleTxUpgradeEnabled) { byte[] propToken = info.Context.PropagationToken; if (propToken != null) { try { return OleTxTransactionInfo.UnmarshalPropagationToken(propToken); } catch (TransactionException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Warning); } // Fall back to WS-AT unmarshal if (DiagnosticUtility.ShouldTraceInformation) DiagnosticUtility.DiagnosticTrace.TraceEvent(TraceEventType.Information, TraceCode.TxFailedToNegotiateOleTx, SR.GetString(SR.TraceCodeTxFailedToNegotiateOleTx, info.Context.Identifier)); } } // Optimization: if the context's registration service points to our local TM, we can // skip the CreateCoordinationContext step CoordinationContext localContext = info.Context; if (!this.wsatConfig.IsLocalRegistrationService(localContext.RegistrationService, this.protocolVersion)) { // Our WS-AT protocol service for the context's protocol version should be enabled if (!this.wsatConfig.IsProtocolServiceEnabled(this.protocolVersion)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new TransactionException(SR.GetString(SR.WsatProtocolServiceDisabled, this.protocolVersion))); } // We should have enabled inbound transactions if (!this.wsatConfig.InboundEnabled) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new TransactionException(SR.GetString(SR.InboundTransactionsDisabled))); } // The sender should have enabled both WS-AT and outbound transactions if (this.wsatConfig.IsDisabledRegistrationService(localContext.RegistrationService)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new TransactionException(SR.GetString(SR.SourceTransactionsDisabled))); } // Ask the WS-AT protocol service to unmarshal the transaction localContext = CreateCoordinationContext(info); } Guid transactionId = localContext.LocalTransactionId; if (transactionId == Guid.Empty) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new TransactionException(SR.GetString(SR.InvalidCoordinationContextTransactionId))); } byte[] propagationToken = MarshalPropagationToken(ref transactionId, localContext.IsolationLevel, localContext.IsolationFlags, localContext.Description); return OleTxTransactionInfo.UnmarshalPropagationToken(propagationToken); } //============================================================================================= CoordinationContext CreateCoordinationContext(WsatTransactionInfo info) { CreateCoordinationContext cccMessage = new CreateCoordinationContext(this.protocolVersion); cccMessage.CurrentContext = info.Context; cccMessage.IssuedToken = info.IssuedToken; try { // This was necessary during some portions of WCF 1.0 development // It is probably not needed now. However, it seems conceptually // solid to separate this operation from the incoming app message as // much as possible. There have also been enough ServiceModel bugs in // this area that it does not seem wise to remove this at the moment // (2006/3/30, WCF 1.0 RC1 milestone) using (new OperationContextScope((OperationContext)null)) { return Enlist(ref cccMessage).CoordinationContext; } } catch (WsatFaultException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Error); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new TransactionException(SR.GetString(SR.UnmarshalTransactionFaulted, e.Message), e)); } catch (WsatSendFailureException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Error); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new TransactionManagerCommunicationException(SR.GetString(SR.TMCommunicationError), e)); } } //============================================================================================== CreateCoordinationContextResponse Enlist(ref CreateCoordinationContext cccMessage) { int attempts = 0; while (true) { ActivationProxy proxy = GetActivationProxy(); EndpointAddress address = proxy.To; EndpointAddress localActivationService = this.wsatConfig.LocalActivationService(this.protocolVersion); EndpointAddress remoteActivationService = this.wsatConfig.RemoteActivationService(this.protocolVersion); try { return proxy.SendCreateCoordinationContext(ref cccMessage); } catch (WsatSendFailureException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Warning); // Don't retry if we're not likely to succeed on the next pass Exception inner = e.InnerException; if (inner is TimeoutException || inner is QuotaExceededException || inner is FaultException) throw; // Give up after 10 attempts if (attempts > 10) throw; if (attempts > 5 && remoteActivationService != null && ReferenceEquals(address, localActivationService)) { // Switch over to the remote activation service. // In clustered scenarios this uses the cluster name, // so it should always work if the resource is online // This covers the case where we were using a local cluster // resource which failed over to another node address = remoteActivationService; } } finally { proxy.Release(); } TryStartMsdtcService(); // We need to refresh our proxy here because the channel is sessionful // and may simply decided to enter the faulted state if something fails. RefreshActivationProxy(address); // Don't spin Thread.Sleep(0); attempts++; } } //============================================================================================= void TryStartMsdtcService() { try { TransactionInterop.GetWhereabouts(); } catch (TransactionException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Warning); } } //============================================================================================== ActivationProxy GetActivationProxy() { if (this.activationProxy == null) { RefreshActivationProxy(null); } lock (this.proxyLock) { ActivationProxy proxy = this.activationProxy; proxy.AddRef(); return proxy; } } //============================================================================================== void RefreshActivationProxy(EndpointAddress suggestedAddress) { // Pick an address in the following order... EndpointAddress address = suggestedAddress; if (address == null) { address = this.wsatConfig.LocalActivationService(this.protocolVersion); if (address == null) { address = this.wsatConfig.RemoteActivationService(this.protocolVersion); } } if (!(address != null)) { // tx processing requires failfast when state is inconsistent DiagnosticUtility.FailFast("Must have valid activation service address"); } lock (this.proxyLock) { ActivationProxy newProxy = CreateActivationProxy(address); if (this.activationProxy != null) this.activationProxy.Release(); this.activationProxy = newProxy; } } //============================================================================================= ActivationProxy CreateActivationProxy(EndpointAddress address) { CoordinationService coordination = GetCoordinationService(); try { return coordination.CreateActivationProxy(address, false); } catch (CreateChannelFailureException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Error); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new TransactionException(SR.GetString(SR.WsatProxyCreationFailed), e)); } } //============================================================================================== CoordinationService GetCoordinationService() { if (this.coordinationService == null) { lock (this.proxyLock) { if (this.coordinationService == null) { try { CoordinationServiceConfiguration config = new CoordinationServiceConfiguration(); config.Mode = CoordinationServiceMode.Formatter; config.RemoteClientsEnabled = this.wsatConfig.RemoteActivationService(this.protocolVersion) != null; this.coordinationService = new CoordinationService(config, this.protocolVersion); } catch (MessagingInitializationException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Error); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new TransactionException(SR.GetString(SR.WsatMessagingInitializationFailed), e)); } } } } return this.coordinationService; } //------------------------------------------------------------------------------- // Marshal/Unmarshaling related stuff //------------------------------------------------------------------------------- // Keep a propagation token around as a template for hydrating transactions static byte[] fixedPropagationToken; static byte[] CreateFixedPropagationToken() { if (fixedPropagationToken == null) { CommittableTransaction tx = new CommittableTransaction(); byte[] token = TransactionInterop.GetTransmitterPropagationToken(tx); // Don't abort the transaction. People notice this and do not like it. try { tx.Commit(); } catch (TransactionException e) { DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); } Interlocked.CompareExchange(ref fixedPropagationToken, token, null); } byte[] tokenCopy = new byte[fixedPropagationToken.Length]; Array.Copy(fixedPropagationToken, tokenCopy, fixedPropagationToken.Length); return tokenCopy; } // This is what a propagation token looks like: // // struct PropagationToken // { // DWORD dwVersionMin; // DWORD dwVersionMax; // GUID guidTx; // ISOLATIONLEVEL isoLevel; // ISOFLAG isoFlags; // ULONG cbSourceTmAddr; // char szDesc[40]; // [etc] // } static byte[] MarshalPropagationToken(ref Guid transactionId, IsolationLevel isoLevel, IsolationFlags isoFlags, string description) { const int offsetof_guidTx = 8; const int offsetof_isoLevel = 24; const int offsetof_isoFlags = 28; const int offsetof_szDesc = 36; const int MaxDescriptionLength = 39; byte[] token = CreateFixedPropagationToken(); // Replace transaction id byte[] transactionIdBytes = transactionId.ToByteArray(); Array.Copy(transactionIdBytes, 0, token, offsetof_guidTx, transactionIdBytes.Length); // Replace isolation level byte[] isoLevelBytes = BitConverter.GetBytes((int) ConvertIsolationLevel(isoLevel)); Array.Copy(isoLevelBytes, 0, token, offsetof_isoLevel, isoLevelBytes.Length); // Replace isolation flags byte[] isoFlagsBytes = BitConverter.GetBytes((int) isoFlags); Array.Copy(isoFlagsBytes, 0, token, offsetof_isoFlags, isoFlagsBytes.Length); // Replace description if (!string.IsNullOrEmpty(description)) { byte[] descriptionBytes = Encoding.UTF8.GetBytes(description); int copyDescriptionBytes = Math.Min(descriptionBytes.Length, MaxDescriptionLength); Array.Copy(descriptionBytes, 0, token, offsetof_szDesc, copyDescriptionBytes); token[offsetof_szDesc + copyDescriptionBytes] = 0; } return token; } enum ProxyIsolationLevel : int { Unspecified = -1, Chaos = 0x10, ReadUncommitted = 0x100, Browse = 0x100, CursorStability = 0x1000, ReadCommitted = 0x1000, RepeatableRead = 0x10000, Serializable = 0x100000, Isolated = 0x100000 } static ProxyIsolationLevel ConvertIsolationLevel(IsolationLevel IsolationLevel) { ProxyIsolationLevel retVal; switch (IsolationLevel) { case IsolationLevel.Serializable: retVal = ProxyIsolationLevel.Serializable; break; case IsolationLevel.RepeatableRead: retVal = ProxyIsolationLevel.RepeatableRead; break; case IsolationLevel.ReadCommitted: retVal = ProxyIsolationLevel.ReadCommitted; break; case IsolationLevel.ReadUncommitted: retVal = ProxyIsolationLevel.ReadUncommitted; break; case IsolationLevel.Unspecified: retVal = ProxyIsolationLevel.Unspecified; break; default: retVal = ProxyIsolationLevel.Serializable; break; } return retVal; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- FixedSOMSemanticBox.cs
- NativeMethods.cs
- ErrorStyle.cs
- LayoutEditorPart.cs
- LastQueryOperator.cs
- WebServiceData.cs
- DBCommandBuilder.cs
- Substitution.cs
- NullNotAllowedCollection.cs
- ToolStripSettings.cs
- AsymmetricKeyExchangeDeformatter.cs
- EdmScalarPropertyAttribute.cs
- TextEditorCharacters.cs
- SafeCancelMibChangeNotify.cs
- ToolStripSettings.cs
- MailMessage.cs
- ListBox.cs
- CompiledRegexRunnerFactory.cs
- NonParentingControl.cs
- EventMappingSettings.cs
- TypedTableBase.cs
- AppDomainUnloadedException.cs
- OracleConnection.cs
- RNGCryptoServiceProvider.cs
- UriWriter.cs
- HttpPostedFile.cs
- AbstractExpressions.cs
- PropertyGroupDescription.cs
- SqlBulkCopyColumnMappingCollection.cs
- EntityObject.cs
- PropertyEmitterBase.cs
- SkewTransform.cs
- VirtualizingStackPanel.cs
- DrawingImage.cs
- WhiteSpaceTrimStringConverter.cs
- ProtectedProviderSettings.cs
- ExclusiveTcpTransportManager.cs
- FileDataSourceCache.cs
- ApplicationGesture.cs
- shaperfactory.cs
- BackEase.cs
- GridViewColumn.cs
- FtpRequestCacheValidator.cs
- LabelEditEvent.cs
- VerificationException.cs
- EventManager.cs
- XmlUtf8RawTextWriter.cs
- DataGridSortCommandEventArgs.cs
- ObjectListCommandEventArgs.cs
- _SslState.cs
- WebPartVerbsEventArgs.cs
- DesignerContextDescriptor.cs
- StatusBarItem.cs
- ContextMenuService.cs
- ResourceDisplayNameAttribute.cs
- ExpandCollapsePatternIdentifiers.cs
- WSTrust.cs
- XPathAxisIterator.cs
- DispatcherHookEventArgs.cs
- ZoneButton.cs
- SqlTrackingService.cs
- OleAutBinder.cs
- TransactionTraceIdentifier.cs
- TextSegment.cs
- TdsParser.cs
- ConnectorRouter.cs
- RtType.cs
- DoubleCollectionConverter.cs
- WebBrowsableAttribute.cs
- InputLanguageSource.cs
- DesignerDataRelationship.cs
- DataSourceXmlClassAttribute.cs
- ConnectionStringsExpressionBuilder.cs
- PasswordBoxAutomationPeer.cs
- SqlCrossApplyToCrossJoin.cs
- PassportPrincipal.cs
- Avt.cs
- StateBag.cs
- DetailsViewPageEventArgs.cs
- UIHelper.cs
- CustomSignedXml.cs
- HybridDictionary.cs
- TraceHelpers.cs
- VirtualDirectoryMappingCollection.cs
- StylusEditingBehavior.cs
- PrintControllerWithStatusDialog.cs
- TreeWalker.cs
- DataPagerFieldItem.cs
- unsafenativemethodsother.cs
- IInstanceContextProvider.cs
- IntellisenseTextBox.designer.cs
- UnitySerializationHolder.cs
- SystemMulticastIPAddressInformation.cs
- _KerberosClient.cs
- ControlParameter.cs
- DbSourceCommand.cs
- ParagraphVisual.cs
- WindowInteractionStateTracker.cs
- XamlValidatingReader.cs
- ToolStripMenuItem.cs