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
- TriggerActionCollection.cs
- DataGridCommandEventArgs.cs
- OutputScopeManager.cs
- XmlSchemaSimpleContentRestriction.cs
- DrawTreeNodeEventArgs.cs
- ChannelServices.cs
- GenerateHelper.cs
- SecurityStateEncoder.cs
- FileVersionInfo.cs
- ProgressBarBrushConverter.cs
- Calendar.cs
- XmlSchemaObjectCollection.cs
- CodeStatement.cs
- WrappedReader.cs
- XmlSchemaChoice.cs
- InteropDesigner.xaml.cs
- FieldNameLookup.cs
- Html32TextWriter.cs
- ObjectItemCollectionAssemblyCacheEntry.cs
- InheritanceAttribute.cs
- XPathMultyIterator.cs
- AutomationEventArgs.cs
- BaseUriHelper.cs
- DbParameterCollection.cs
- OleDbDataAdapter.cs
- InvalidOperationException.cs
- AccessibleObject.cs
- CallbackValidatorAttribute.cs
- MDIWindowDialog.cs
- RegexMatch.cs
- Thumb.cs
- VectorAnimation.cs
- HttpHeaderCollection.cs
- UntrustedRecipientException.cs
- FontFamilyConverter.cs
- ObjectListCommandsPage.cs
- StringTraceRecord.cs
- CustomValidator.cs
- StylusCaptureWithinProperty.cs
- DrawListViewSubItemEventArgs.cs
- ErrorLog.cs
- Behavior.cs
- SqlClientFactory.cs
- BitSet.cs
- SqlStream.cs
- LayoutUtils.cs
- MatrixTransform3D.cs
- SecurityUtils.cs
- IUnknownConstantAttribute.cs
- TemplatePagerField.cs
- ChameleonKey.cs
- Speller.cs
- ClientTargetSection.cs
- ObjectParameterCollection.cs
- GZipStream.cs
- CssStyleCollection.cs
- BinaryObjectWriter.cs
- EventLogEntryCollection.cs
- ExtenderControl.cs
- XmlStringTable.cs
- ItemCheckEvent.cs
- TimelineClockCollection.cs
- SerialStream.cs
- DataGridTextBox.cs
- TrackingMemoryStreamFactory.cs
- WebConvert.cs
- BinaryFormatterSinks.cs
- ListViewItemMouseHoverEvent.cs
- SiteMapSection.cs
- HttpProfileBase.cs
- DirtyTextRange.cs
- PresentationAppDomainManager.cs
- XPathExpr.cs
- TextLineBreak.cs
- DynamicResourceExtensionConverter.cs
- EditCommandColumn.cs
- TemplatePropertyEntry.cs
- BevelBitmapEffect.cs
- UnknownBitmapDecoder.cs
- CommentEmitter.cs
- Point4DConverter.cs
- ThemeDictionaryExtension.cs
- XmlMembersMapping.cs
- CollectionViewSource.cs
- DirectoryObjectSecurity.cs
- RegistrationServices.cs
- PlacementWorkspace.cs
- MobileErrorInfo.cs
- X509Certificate2.cs
- RadioButtonRenderer.cs
- IndexedString.cs
- ReadOnlyTernaryTree.cs
- X509ChainPolicy.cs
- ConfigXmlSignificantWhitespace.cs
- CaretElement.cs
- SynchronizedInputAdaptor.cs
- IpcManager.cs
- SoapSchemaImporter.cs
- RepeatButtonAutomationPeer.cs
- CodeExpressionCollection.cs