1 //----------------------------------------------------------------------------- 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //----------------------------------------------------------------------------- 4 5 namespace System.ServiceModel.Dispatcher 6 { 7 using System; 8 using System.Reflection; 9 using System.Runtime.Diagnostics; 10 using System.ServiceModel.Diagnostics; 11 using System.ServiceModel.Diagnostics.Application; 12 using System.Globalization; 13 using System.Threading; 14 using System.Collections; 15 using System.Diagnostics; 16 using System.Security; 17 using System.Runtime; 18 19 class SyncMethodInvoker : IOperationInvoker 20 { 21 Type type; 22 string methodName; 23 MethodInfo method; 24 InvokeDelegate invokeDelegate; 25 int inputParameterCount; 26 int outputParameterCount; 27 SyncMethodInvoker(MethodInfo method)28 public SyncMethodInvoker(MethodInfo method) 29 { 30 if (method == null) 31 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("method")); 32 33 this.method = method; 34 } 35 SyncMethodInvoker(Type type, string methodName)36 public SyncMethodInvoker(Type type, string methodName) 37 { 38 if (type == null) 39 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("type")); 40 41 if (methodName == null) 42 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("methodName")); 43 44 this.type = type; 45 this.methodName = methodName; 46 } 47 48 public bool IsSynchronous 49 { 50 get { return true; } 51 } 52 53 public MethodInfo Method 54 { 55 get 56 { 57 if (method == null) 58 method = type.GetMethod(methodName); 59 return method; 60 } 61 } 62 63 public string MethodName 64 { 65 get 66 { 67 if (methodName == null) 68 methodName = method.Name; 69 return methodName; 70 } 71 } 72 AllocateInputs()73 public object[] AllocateInputs() 74 { 75 EnsureIsInitialized(); 76 77 return EmptyArray.Allocate(this.inputParameterCount); 78 } 79 Invoke(object instance, object[] inputs, out object[] outputs)80 public object Invoke(object instance, object[] inputs, out object[] outputs) 81 { 82 EnsureIsInitialized(); 83 84 if (instance == null) 85 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxNoServiceObject))); 86 if (inputs == null) 87 { 88 if (this.inputParameterCount > 0) 89 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceNull, this.inputParameterCount))); 90 } 91 else if (inputs.Length != this.inputParameterCount) 92 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInputParametersToServiceInvalid, this.inputParameterCount, inputs.Length))); 93 94 outputs = EmptyArray.Allocate(this.outputParameterCount); 95 96 long startCounter = 0; 97 long stopCounter = 0; 98 long beginOperation = 0; 99 bool callSucceeded = false; 100 bool callFaulted = false; 101 102 if (PerformanceCounters.PerformanceCountersEnabled) 103 { 104 PerformanceCounters.MethodCalled(this.MethodName); 105 try 106 { 107 if (System.ServiceModel.Channels.UnsafeNativeMethods.QueryPerformanceCounter(out startCounter) == 0) 108 { 109 startCounter = -1; 110 } 111 } 112 catch (SecurityException securityException) 113 { 114 DiagnosticUtility.TraceHandledException(securityException, TraceEventType.Warning); 115 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 116 new SecurityException(SR.GetString( 117 SR.PartialTrustPerformanceCountersNotEnabled), securityException)); 118 } 119 } 120 121 EventTraceActivity eventTraceActivity = null; 122 if (TD.OperationCompletedIsEnabled() || 123 TD.OperationFaultedIsEnabled() || 124 TD.OperationFailedIsEnabled()) 125 { 126 beginOperation = DateTime.UtcNow.Ticks; 127 OperationContext context = OperationContext.Current; 128 if (context != null && context.IncomingMessage != null) 129 { 130 eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(context.IncomingMessage); 131 } 132 } 133 134 object returnValue; 135 try 136 { 137 ServiceModelActivity activity = null; 138 IDisposable boundActivity = null; 139 if (DiagnosticUtility.ShouldUseActivity) 140 { 141 activity = ServiceModelActivity.CreateBoundedActivity(true); 142 boundActivity = activity; 143 } 144 else if (TraceUtility.MessageFlowTracingOnly) 145 { 146 Guid activityId = TraceUtility.GetReceivedActivityId(OperationContext.Current); 147 if (activityId != Guid.Empty) 148 { 149 DiagnosticTraceBase.ActivityId = activityId; 150 } 151 } 152 else if (TraceUtility.ShouldPropagateActivity) 153 { 154 //Message flow tracing only scenarios use a light-weight ActivityID management logic 155 Guid activityId = ActivityIdHeader.ExtractActivityId(OperationContext.Current.IncomingMessage); 156 if (activityId != Guid.Empty) 157 { 158 boundActivity = Activity.CreateActivity(activityId); 159 } 160 } 161 162 using (boundActivity) 163 { 164 if (DiagnosticUtility.ShouldUseActivity) 165 { 166 ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityExecuteMethod, this.method.DeclaringType.FullName, this.method.Name), ActivityType.ExecuteUserCode); 167 } 168 if (TD.OperationInvokedIsEnabled()) 169 { 170 TD.OperationInvoked(eventTraceActivity, this.MethodName, TraceUtility.GetCallerInfo(OperationContext.Current)); 171 } 172 returnValue = this.invokeDelegate(instance, inputs, outputs); 173 callSucceeded = true; 174 } 175 } 176 catch (System.ServiceModel.FaultException) 177 { 178 callFaulted = true; 179 throw; 180 } 181 catch (System.Security.SecurityException e) 182 { 183 DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning); 184 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(AuthorizationBehavior.CreateAccessDeniedFaultException()); 185 } 186 finally 187 { 188 if (PerformanceCounters.PerformanceCountersEnabled) 189 { 190 long elapsedTime = 0; 191 if (startCounter >= 0 && System.ServiceModel.Channels.UnsafeNativeMethods.QueryPerformanceCounter(out stopCounter) != 0) 192 { 193 elapsedTime = stopCounter - startCounter; 194 } 195 196 if (callSucceeded) // call succeeded 197 { 198 PerformanceCounters.MethodReturnedSuccess(this.MethodName, elapsedTime); 199 } 200 else if (callFaulted) // call faulted 201 { 202 PerformanceCounters.MethodReturnedFault(this.MethodName, elapsedTime); 203 } 204 else // call failed 205 { 206 PerformanceCounters.MethodReturnedError(this.MethodName, elapsedTime); 207 } 208 } 209 210 if (beginOperation != 0) 211 { 212 if (callSucceeded) 213 { 214 if (TD.OperationCompletedIsEnabled()) 215 { 216 TD.OperationCompleted(eventTraceActivity, this.methodName, 217 TraceUtility.GetUtcBasedDurationForTrace(beginOperation)); 218 } 219 } 220 else if (callFaulted) 221 { 222 if (TD.OperationFaultedIsEnabled()) 223 { 224 TD.OperationFaulted(eventTraceActivity, this.methodName, 225 TraceUtility.GetUtcBasedDurationForTrace(beginOperation)); 226 } 227 } 228 else 229 { 230 if (TD.OperationFailedIsEnabled()) 231 { 232 TD.OperationFailed(eventTraceActivity, this.methodName, 233 TraceUtility.GetUtcBasedDurationForTrace(beginOperation)); 234 } 235 } 236 } 237 } 238 239 return returnValue; 240 } 241 InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)242 public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state) 243 { 244 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException()); 245 } 246 InvokeEnd(object instance, out object[] outputs, IAsyncResult result)247 public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result) 248 { 249 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException()); 250 } 251 EnsureIsInitialized()252 void EnsureIsInitialized() 253 { 254 if (this.invokeDelegate == null) 255 { 256 EnsureIsInitializedCore(); 257 } 258 } 259 EnsureIsInitializedCore()260 void EnsureIsInitializedCore() 261 { 262 // Only pass locals byref because InvokerUtil may store temporary results in the byref. 263 // If two threads both reference this.count, temporary results may interact. 264 int inputParameterCount; 265 int outputParameterCount; 266 InvokeDelegate invokeDelegate = new InvokerUtil().GenerateInvokeDelegate(this.Method, out inputParameterCount, out outputParameterCount); 267 this.outputParameterCount = outputParameterCount; 268 this.inputParameterCount = inputParameterCount; 269 this.invokeDelegate = invokeDelegate; // must set this last due to ---- 270 } 271 } 272 } 273