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
- XNameConverter.cs
- PropertyPathWorker.cs
- ProcessInfo.cs
- NotifyIcon.cs
- AudioDeviceOut.cs
- ApplicationBuildProvider.cs
- PropertyDescriptors.cs
- CryptoStream.cs
- ParserOptions.cs
- InvokeDelegate.cs
- SessionStateItemCollection.cs
- CookieParameter.cs
- ToolStripRenderEventArgs.cs
- RootBuilder.cs
- NameSpaceEvent.cs
- RepeatButtonAutomationPeer.cs
- ExpressionVisitorHelpers.cs
- XmlNullResolver.cs
- TraceEventCache.cs
- IItemProperties.cs
- NavigateUrlConverter.cs
- StandardToolWindows.cs
- FullTrustAssembly.cs
- IDictionary.cs
- Stacktrace.cs
- Domain.cs
- Util.cs
- SchemaComplexType.cs
- MethodSet.cs
- coordinatorscratchpad.cs
- Win32Interop.cs
- TableCell.cs
- TemplateAction.cs
- TransactionChannelFaultConverter.cs
- LineServicesCallbacks.cs
- COAUTHINFO.cs
- CodeValidator.cs
- EntityType.cs
- EntityDataSourceWizardForm.cs
- InternalControlCollection.cs
- CheckBoxRenderer.cs
- AutoResetEvent.cs
- SafeNativeMethodsMilCoreApi.cs
- FileSystemInfo.cs
- HealthMonitoringSectionHelper.cs
- NativeRecognizer.cs
- DbDataRecord.cs
- XmlCharType.cs
- AsyncContentLoadedEventArgs.cs
- OdbcPermission.cs
- DbMetaDataCollectionNames.cs
- ExpanderAutomationPeer.cs
- Reference.cs
- ErrorTableItemStyle.cs
- TripleDES.cs
- _BasicClient.cs
- ProbeDuplexCD1AsyncResult.cs
- FillRuleValidation.cs
- TextTreeInsertUndoUnit.cs
- HostingMessageProperty.cs
- BitmapImage.cs
- SqlCommandSet.cs
- Rfc4050KeyFormatter.cs
- TextWriterEngine.cs
- StateRuntime.cs
- PropertyInfoSet.cs
- securestring.cs
- _ReceiveMessageOverlappedAsyncResult.cs
- CapabilitiesPattern.cs
- StorageAssociationTypeMapping.cs
- RoleService.cs
- ServiceDocumentFormatter.cs
- LeftCellWrapper.cs
- PromptEventArgs.cs
- ItemDragEvent.cs
- ByteArrayHelperWithString.cs
- DataGridColumnCollection.cs
- DataServiceConfiguration.cs
- BitmapMetadata.cs
- cache.cs
- WhitespaceRuleLookup.cs
- NamedPipeConnectionPoolSettingsElement.cs
- SmtpException.cs
- PointAnimationClockResource.cs
- DefaultShape.cs
- SoundPlayerAction.cs
- SoapEnumAttribute.cs
- serverconfig.cs
- SystemWebExtensionsSectionGroup.cs
- VSWCFServiceContractGenerator.cs
- InputLangChangeRequestEvent.cs
- PolicyReader.cs
- OdbcConnectionHandle.cs
- GuidelineCollection.cs
- RelatedImageListAttribute.cs
- XmlDataSource.cs
- QilVisitor.cs
- ImageKeyConverter.cs
- ImageCodecInfo.cs
- Decorator.cs