X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.ServiceModel%2FSystem.ServiceModel%2FClientRuntimeChannel.cs;h=2e2b0d60b0860a432a7a5229b0f1e409a0ab9af2;hb=e4d491cdd7ce10b2b222789ae038e5d63c9531f4;hp=d0aeb8e78bea9efd658270de9be4137c5453d7c5;hpb=033c49897292e6646a917258713a17c86b9994af;p=mono.git diff --git a/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs b/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs index d0aeb8e78be..2e2b0d60b08 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs @@ -46,7 +46,7 @@ namespace System.ServiceModel.MonoInternal { ContractDescription Contract { get; } - object Process (MethodBase method, string operationName, object [] parameters); + object Process (MethodBase method, string operationName, object [] parameters, OperationContext context); IAsyncResult BeginProcess (MethodBase method, string operationName, object [] parameters, AsyncCallback callback, object asyncState); @@ -67,12 +67,13 @@ namespace System.ServiceModel.MonoInternal TimeSpan default_open_timeout, default_close_timeout; IChannel channel; IChannelFactory factory; - OperationContext context; + TimeSpan? operation_timeout = null; + #region delegates readonly ProcessDelegate _processDelegate; - delegate object ProcessDelegate (MethodBase method, string operationName, object [] parameters); + delegate object ProcessDelegate (MethodBase method, string operationName, bool isAsync, ref object [] parameters, OperationContext context); readonly RequestDelegate requestDelegate; @@ -93,6 +94,8 @@ namespace System.ServiceModel.MonoInternal { if (runtime == null) throw new ArgumentNullException ("runtime"); + if (messageVersion == null) + throw new ArgumentNullException ("messageVersion"); this.runtime = runtime; this.remote_address = remoteAddress; if (runtime.Via == null) @@ -107,7 +110,6 @@ namespace System.ServiceModel.MonoInternal // default values AllowInitializationUI = true; - OperationTimeout = TimeSpan.FromMinutes (1); if (contextChannel != null) channel = contextChannel; @@ -196,7 +198,6 @@ namespace System.ServiceModel.MonoInternal } } -#if !MOONLIGHT public override bool WaitOne (int millisecondsTimeout, bool exitContext) { return WaitHandle.WaitAll (ResultWaitHandles, millisecondsTimeout, exitContext); @@ -206,7 +207,6 @@ namespace System.ServiceModel.MonoInternal { return WaitHandle.WaitAll (ResultWaitHandles, timeout, exitContext); } -#endif } class DisplayUIAsyncResult : IAsyncResult @@ -323,8 +323,17 @@ namespace System.ServiceModel.MonoInternal } } - [MonoTODO] - public TimeSpan OperationTimeout { get; set; } + public TimeSpan OperationTimeout { + get { + if (!this.operation_timeout.HasValue) { + this.operation_timeout = DefaultCommunicationTimeouts.Instance.ReceiveTimeout; + } + return this.operation_timeout.Value; + } + set { + this.operation_timeout = value; + } + } public IOutputSession OutputSession { get { @@ -418,6 +427,8 @@ namespace System.ServiceModel.MonoInternal public T GetProperty () where T : class { + if (typeof (T) == typeof (MessageVersion)) + return (T) (object) message_version; return OperationChannel.GetProperty (); } @@ -435,77 +446,59 @@ namespace System.ServiceModel.MonoInternal #region Request/Output processing - class TempAsyncResult : IAsyncResult - { - public TempAsyncResult (object returnValue, object state) - { - ReturnValue = returnValue; - AsyncState = state; - CompletedSynchronously = true; - IsCompleted = true; - AsyncWaitHandle = new ManualResetEvent (true); - } - - public object ReturnValue { get; set; } - public object AsyncState { get; set; } - public bool CompletedSynchronously { get; set; } - public bool IsCompleted { get; set; } - public WaitHandle AsyncWaitHandle { get; set; } - } - public IAsyncResult BeginProcess (MethodBase method, string operationName, object [] parameters, AsyncCallback callback, object asyncState) { - if (context != null) - throw new InvalidOperationException ("another operation is in progress"); - context = OperationContext.Current; - - // FIXME: this is a workaround for bug #633945 - switch (Environment.OSVersion.Platform) { - case PlatformID.Unix: - case PlatformID.MacOSX: - return _processDelegate.BeginInvoke (method, operationName, parameters, callback, asyncState); - default: - var result = Process (method, operationName, parameters); - var ret = new TempAsyncResult (result, asyncState); - if (callback != null) - callback (ret); - return ret; - } + var p = parameters; + var retval = _processDelegate.BeginInvoke (method, operationName, true, ref p, OperationContext.Current, callback, asyncState); + if (p != parameters) + throw new InvalidOperationException (); + return retval; } public object EndProcess (MethodBase method, string operationName, object [] parameters, IAsyncResult result) { - context = null; if (result == null) throw new ArgumentNullException ("result"); if (parameters == null) throw new ArgumentNullException ("parameters"); - // FIXME: the method arguments should be verified to be - // identical to the arguments in the corresponding begin method. - // FIXME: this is a workaround for bug #633945 - switch (Environment.OSVersion.Platform) { - case PlatformID.Unix: - case PlatformID.MacOSX: - return _processDelegate.EndInvoke (result); - default: - return ((TempAsyncResult) result).ReturnValue; - } + + object[] p = parameters; + var retval = _processDelegate.EndInvoke (ref p, result); + if (p == parameters) + return retval; + + if (p.Length != parameters.Length) + throw new InvalidOperationException (); + Array.Copy (p, parameters, p.Length); + return retval; } - public object Process (MethodBase method, string operationName, object [] parameters) + public object Process (MethodBase method, string operationName, object [] parameters, OperationContext context) { + var p = parameters; + var retval = Process (method, operationName, false, ref p, context); + if (p != parameters) + throw new InvalidOperationException (); + return retval; + } + + object Process (MethodBase method, string operationName, bool isAsync, ref object [] parameters, OperationContext context) + { + var previousContext = OperationContext.Current; try { - return DoProcess (method, operationName, parameters); + // Inherit the context from the calling thread + OperationContext.Current = context; + + return DoProcess (method, operationName, isAsync, ref parameters, context); } catch (Exception ex) { -#if MOONLIGHT // just for debugging - Console.Write ("Exception in async operation: "); - Console.WriteLine (ex); -#endif throw; + } finally { + // Reset the context before the thread goes back into the pool + OperationContext.Current = previousContext; } } - object DoProcess (MethodBase method, string operationName, object [] parameters) + object DoProcess (MethodBase method, string operationName, bool isAsync, ref object [] parameters, OperationContext context) { if (AllowInitializationUI) DisplayInitializationUI (); @@ -515,9 +508,9 @@ namespace System.ServiceModel.MonoInternal Open (); if (!od.IsOneWay) - return Request (od, parameters); + return Request (od, isAsync, ref parameters, context); else { - Output (od, parameters); + Output (od, parameters, context); return null; } } @@ -535,17 +528,17 @@ namespace System.ServiceModel.MonoInternal return od; } - void Output (OperationDescription od, object [] parameters) + void Output (OperationDescription od, object [] parameters, OperationContext context) { ClientOperation op = runtime.Operations [od.Name]; - Send (CreateRequest (op, parameters), OperationTimeout); + Send (CreateRequest (op, parameters, context), OperationTimeout); } - object Request (OperationDescription od, object [] parameters) + object Request (OperationDescription od, bool isAsync, ref object [] parameters, OperationContext context) { ClientOperation op = runtime.Operations [od.Name]; object [] inspections = new object [runtime.MessageInspectors.Count]; - Message req = CreateRequest (op, parameters); + Message req = CreateRequest (op, parameters, context); for (int i = 0; i < inspections.Length; i++) inspections [i] = runtime.MessageInspectors [i].BeforeSendRequest (ref req, this); @@ -561,14 +554,12 @@ namespace System.ServiceModel.MonoInternal Type detailType = typeof (ExceptionDetail); var freader = fault.GetReaderAtDetailContents (); DataContractSerializer ds = null; -#if !NET_2_1 foreach (var fci in op.FaultContractInfos) if (res.Headers.Action == fci.Action || fci.Serializer.IsStartObject (freader)) { detailType = fci.Detail; ds = fci.Serializer; break; } -#endif if (ds == null) ds = new DataContractSerializer (detailType); var detail = ds.ReadObject (freader); @@ -584,10 +575,15 @@ namespace System.ServiceModel.MonoInternal for (int i = 0; i < inspections.Length; i++) runtime.MessageInspectors [i].AfterReceiveReply (ref res, inspections [i]); - if (op.DeserializeReply) - return op.Formatter.DeserializeReply (res, parameters); - else + if (!op.DeserializeReply) return res; + + if (isAsync && od.EndMethod != null) { + var endParams = od.EndMethod.GetParameters (); + parameters = new object [endParams.Length - 1]; + } + + return op.Formatter.DeserializeReply (res, parameters); } #region Message-based Request() and Send() @@ -602,6 +598,9 @@ namespace System.ServiceModel.MonoInternal internal virtual Message RequestCorrelated (Message msg, TimeSpan timeout, IOutputChannel channel) { + // FIXME: implement ConcurrencyMode check: + // if it is .Single && this instance for a callback channel && the operation is invoked inside service operation, then error. + DateTime startTime = DateTime.Now; OutputChannel.Send (msg, timeout); return ((IDuplexChannel) channel).Receive (timeout - (DateTime.Now - startTime)); @@ -636,7 +635,7 @@ namespace System.ServiceModel.MonoInternal } #endregion - Message CreateRequest (ClientOperation op, object [] parameters) + Message CreateRequest (ClientOperation op, object [] parameters, OperationContext context) { MessageVersion version = message_version; if (version == null)