SyncMethodInvoker.cs 11 KB

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