Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 57b23cb

Browse filesBrowse files
committed
Removed redundant callback feature. Tuned some of the state and made it threadlocal for perf. TestServer_Console project now uses a better code path for the perf test.
1 parent 321371f commit 57b23cb
Copy full SHA for 57b23cb

5 files changed

+99-189Lines changed: 99 additions & 189 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎AustinHarris.JsonRpcTestN/Test.cs‎

Copy file name to clipboardExpand all lines: AustinHarris.JsonRpcTestN/Test.cs
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,6 +1929,8 @@ private static void AssertJsonAreEqual(JToken expectedJson, JToken actualJson, s
19291929

19301930
private static void AssertJsonAreEqual(JObject expectedJson, JObject actualJson, string path)
19311931
{
1932+
Console.WriteLine("expected: {0}", expectedJson);
1933+
Console.WriteLine("actual : {0}", actualJson);
19321934
Assert.AreEqual(expectedJson.Count, actualJson.Count, "Count of json object at " + path);
19331935
for (var expectedElementsEnumerator = expectedJson.GetEnumerator(); expectedElementsEnumerator.MoveNext(); )
19341936
{
Collapse file

‎Json-Rpc/Handler.cs‎

Copy file name to clipboardExpand all lines: Json-Rpc/Handler.cs
+54-92Lines changed: 54 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,13 @@ public class Handler
1515
{
1616
#region Members
1717

18-
//private static Handler current;
19-
private static ConcurrentDictionary<string, Handler> _sessionHandlers;
20-
private static string _defaultSessionId;
18+
private static int _sessionHandlerMasterVersion = 1;
19+
[ThreadStatic]
20+
private static int _sessionHandlerLocalVersion = 0;
21+
private static ConcurrentDictionary<string, Handler> _sessionHandlersMaster;
22+
[ThreadStatic]
23+
private static Dictionary<string, Handler> _sessionHandlersLocal;
24+
private static volatile string _defaultSessionId;
2125
#endregion
2226

2327
#region Constructors
@@ -26,8 +30,8 @@ static Handler()
2630
{
2731
//current = new Handler(Guid.NewGuid().ToString());
2832
_defaultSessionId = Guid.NewGuid().ToString();
29-
_sessionHandlers = new ConcurrentDictionary<string, Handler>();
30-
_sessionHandlers[_defaultSessionId] = new Handler(_defaultSessionId);
33+
_sessionHandlersMaster = new ConcurrentDictionary<string, Handler>();
34+
_sessionHandlersMaster[_defaultSessionId] = new Handler(_defaultSessionId);
3135
}
3236

3337
private Handler(string sessionId)
@@ -53,7 +57,17 @@ private Handler(string sessionId)
5357
/// <returns></returns>
5458
public static Handler GetSessionHandler(string sessionId)
5559
{
56-
return _sessionHandlers.GetOrAdd(sessionId, new Handler(sessionId));
60+
if (_sessionHandlerMasterVersion != _sessionHandlerLocalVersion)
61+
{
62+
_sessionHandlersLocal = new Dictionary<string, Handler>(_sessionHandlersMaster);
63+
_sessionHandlerLocalVersion = _sessionHandlerMasterVersion;
64+
}
65+
if (_sessionHandlersLocal.ContainsKey(sessionId))
66+
{
67+
return _sessionHandlersLocal[sessionId];
68+
}
69+
Interlocked.Increment(ref _sessionHandlerMasterVersion);
70+
return _sessionHandlersMaster.GetOrAdd(sessionId, new Handler(sessionId));
5771
}
5872

5973
/// <summary>
@@ -72,7 +86,8 @@ public static Handler GetSessionHandler()
7286
public static void DestroySession(string sessionId)
7387
{
7488
Handler h;
75-
_sessionHandlers.TryRemove(sessionId, out h);
89+
_sessionHandlersMaster.TryRemove(sessionId, out h);
90+
Interlocked.Increment(ref _sessionHandlerMasterVersion);
7691
h.MetaData.Services.Clear();
7792
}
7893
/// <summary>
@@ -93,36 +108,32 @@ public void Destroy()
93108
/// </summary>
94109
public string SessionId { get; private set; }
95110

96-
private static ConcurrentDictionary<int, object> RpcContexts = new ConcurrentDictionary<int, object>();
97-
private static ConcurrentDictionary<int, JsonRpcException> RpcExceptions = new ConcurrentDictionary<int, JsonRpcException>();
98-
99111
/// <summary>
100112
/// Provides access to a context specific to each JsonRpc method invocation.
101113
/// Warning: Must be called from within the execution context of the jsonRpc Method to return the context
102114
/// </summary>
103115
/// <returns></returns>
104116
public static object RpcContext()
105117
{
106-
if (Task.CurrentId == null)
107-
return null;
108-
109-
if (RpcContexts.ContainsKey(Task.CurrentId.Value) == false)
110-
return null;
111-
112-
return RpcContexts[Task.CurrentId.Value];
118+
return __currentRpcContext;
113119
}
114120

121+
[ThreadStatic]
122+
static JsonRpcException __currentRpcException;
115123
/// <summary>
116124
/// Allows you to set the exception used in in the JsonRpc response.
117-
/// Warning: Must be called from within the execution context of the jsonRpc method.
125+
/// Warning: Must be called from the same thread as the jsonRpc method.
118126
/// </summary>
119127
/// <param name="exception"></param>
120128
public static void RpcSetException(JsonRpcException exception)
121129
{
122-
if (Task.CurrentId != null)
123-
RpcExceptions[Task.CurrentId.Value] = exception;
124-
else
125-
throw new InvalidOperationException("This method is only valid when used within the context of a method marked as a JsonRpcMethod, and that method must of been invoked by the JsonRpc Handler.");
130+
__currentRpcException = exception;
131+
}
132+
public static JsonRpcException RpcGetAndRemoveRpcException()
133+
{
134+
var ex = __currentRpcException;
135+
__currentRpcException = null ;
136+
return ex;
126137
}
127138

128139
private AustinHarris.JsonRpc.PreProcessHandler externalPreProcessingHandler;
@@ -136,8 +147,6 @@ public static void RpcSetException(JsonRpcException exception)
136147
/// </summary>
137148
public SMD MetaData { get; set; }
138149

139-
private const string THREAD_CALLBACK_SLOT_NAME ="Callback";
140-
141150
#region Public Methods
142151

143152
/// <summary>
@@ -184,7 +193,7 @@ public void SetPostProcessHandler(AustinHarris.JsonRpc.PostProcessHandler handle
184193
/// <param name="Rpc">JsonRpc Request to be processed</param>
185194
/// <param name="RpcContext">Optional context that will be available from within the jsonRpcMethod.</param>
186195
/// <returns></returns>
187-
public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null, Action<JsonResponse> callback = null)
196+
public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null)
188197
{
189198
AddRpcContext(RpcContext);
190199

@@ -198,7 +207,7 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null, Action<Jso
198207
};
199208
//callback is called - if it is empty then nothing will be done
200209
//return response always- if callback is empty or not
201-
return PostProcess(callback, Rpc, response, RpcContext);
210+
return PostProcess(Rpc, response, RpcContext);
202211
}
203212

204213
SMDService metadata = null;
@@ -217,7 +226,7 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null, Action<Jso
217226
Error = new JsonRpcException(-32601, "Method not found", "The method does not exist / is not available."),
218227
Id = Rpc.Id
219228
};
220-
return PostProcess(callback, Rpc, response, RpcContext);
229+
return PostProcess(Rpc, response, RpcContext);
221230
}
222231

223232
bool isJObject = Rpc.Params is Newtonsoft.Json.Linq.JObject;
@@ -278,7 +287,7 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null, Action<Jso
278287
)),
279288
Id = Rpc.Id
280289
};
281-
return PostProcess(callback, Rpc, response, RpcContext);
290+
return PostProcess(Rpc, response, RpcContext);
282291
}
283292
parameters[i] = CleanUpParameter(jo[metadata.parameters[i].Name], metadata.parameters[i]);
284293
}
@@ -313,7 +322,7 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null, Action<Jso
313322
)),
314323
Id = Rpc.Id
315324
};
316-
return PostProcess(callback, Rpc, response, RpcContext);
325+
return PostProcess(Rpc, response, RpcContext);
317326
}
318327
}
319328

@@ -330,103 +339,72 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null, Action<Jso
330339
)),
331340
Id = Rpc.Id
332341
};
333-
return PostProcess(callback, Rpc, response, RpcContext);
342+
return PostProcess(Rpc, response, RpcContext);
334343
}
335344

336345
try
337346
{
338-
//callback is stored to thread's local storage in order to get it directly from concrete JsonRpcService method implementation
339-
//where callback is just returned from method
340-
Thread.SetData(Thread.GetNamedDataSlot(THREAD_CALLBACK_SLOT_NAME), callback);
341-
342-
343347
var results = handle.DynamicInvoke(parameters);
344348

345349
var last = parameters.LastOrDefault();
346-
JsonRpcException contextException;
347-
if (Task.CurrentId.HasValue && RpcExceptions.TryRemove(Task.CurrentId.Value, out contextException))
350+
var contextException = RpcGetAndRemoveRpcException();
351+
if (contextException != null)
348352
{
349353
JsonResponse response = new JsonResponse() { Error = ProcessException(Rpc, contextException), Id = Rpc.Id };
350-
return PostProcess(callback, Rpc, response, RpcContext);
354+
return PostProcess(Rpc, response, RpcContext);
351355
}
352356
if (expectsRefException && last != null && last is JsonRpcException)
353357
{
354358
JsonResponse response = new JsonResponse() { Error = ProcessException(Rpc, last as JsonRpcException), Id = Rpc.Id };
355-
return PostProcess(callback, Rpc, response, RpcContext);
359+
return PostProcess(Rpc, response, RpcContext);
356360
}
357-
//return response, if callback is set (method is asynchronous) - result could be empty string and future result operations
358-
//will be processed in the callback
359-
return PostProcess(null, Rpc, new JsonResponse() { Result = results }, RpcContext);
361+
return PostProcess(Rpc, new JsonResponse() { Result = results }, RpcContext);
360362
}
361363
catch (Exception ex)
362364
{
363365
JsonResponse response;
364366
if (ex is TargetParameterCountException)
365367
{
366368
response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", ex)) };
367-
return PostProcess(callback, Rpc, response, RpcContext);
369+
return PostProcess(Rpc, response, RpcContext);
368370
}
369371

370372
// We really dont care about the TargetInvocationException, just pass on the inner exception
371373
if (ex is JsonRpcException)
372374
{
373375
response = new JsonResponse() { Error = ProcessException(Rpc, ex as JsonRpcException) };
374-
return PostProcess(callback, Rpc, response, RpcContext);
376+
return PostProcess(Rpc, response, RpcContext);
375377
}
376378
if (ex.InnerException != null && ex.InnerException is JsonRpcException)
377379
{
378380
response = new JsonResponse() { Error = ProcessException(Rpc, ex.InnerException as JsonRpcException) };
379-
return PostProcess(callback, Rpc, response, RpcContext);
381+
return PostProcess(Rpc, response, RpcContext);
380382
}
381383
else if (ex.InnerException != null)
382384
{
383385
response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex.InnerException)) };
384-
return PostProcess(callback, Rpc, response, RpcContext);
386+
return PostProcess(Rpc, response, RpcContext);
385387
}
386388

387389
response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex)) };
388-
return PostProcess(callback, Rpc, response, RpcContext);
390+
return PostProcess(Rpc, response, RpcContext);
389391
}
390392
finally
391393
{
392394
RemoveRpcContext();
393395
}
394396
}
395397
#endregion
396-
/// <summary>
397-
/// Method returns the actual callback set to this thread in Handle() method.
398-
/// If callback is not set, then empty callback is returned.
399-
/// </summary>
400-
/// <returns></returns>
401-
internal Action<JsonResponse> GetAsyncCallback()
402-
{
403-
object o = Thread.GetData(Thread.GetNamedDataSlot(THREAD_CALLBACK_SLOT_NAME));
404-
Action<JsonResponse> callback;
405-
if(o is Action<JsonResponse>)
406-
{
407-
callback = o as Action<JsonResponse>;
408-
}
409-
else
410-
{
411-
callback = delegate(JsonResponse a) { };
412-
}
413-
return callback;
414-
}
415398

399+
[ThreadStatic]
400+
static object __currentRpcContext;
416401
private void AddRpcContext(object RpcContext)
417402
{
418-
if (Task.CurrentId != null)
419-
RpcContexts[Task.CurrentId.Value] = RpcContext;
403+
__currentRpcContext = RpcContext;
420404
}
421405
private void RemoveRpcContext()
422406
{
423-
if (Task.CurrentId != null)
424-
{
425-
var id = Task.CurrentId.Value;
426-
RpcContexts[id] = null;
427-
object va;
428-
RpcContexts.TryRemove(id, out va);
429-
}
407+
__currentRpcContext = null;
430408
}
431409

432410
private JsonRpcException ProcessException(JsonRequest req, JsonRpcException ex)
@@ -449,18 +427,6 @@ internal void SetParseErrorHandler(Func<string, JsonRpcException, JsonRpcExcepti
449427
{
450428
parseErrorHandler = handler;
451429
}
452-
453-
private void RemoveRpcException()
454-
{
455-
if (Task.CurrentId != null)
456-
{
457-
var id = Task.CurrentId.Value;
458-
RpcExceptions[id] = null;
459-
JsonRpcException va;
460-
RpcExceptions.TryRemove(id, out va);
461-
}
462-
}
463-
464430

465431
private object CleanUpParameter(object p, SMDAdditionalParameters metaData)
466432
{
@@ -531,7 +497,7 @@ private JsonRpcException PreProcess(JsonRequest request, object context)
531497
return externalPreProcessingHandler(request, context);
532498
}
533499

534-
private JsonResponse PostProcess(Action<JsonResponse> callback, JsonRequest request, JsonResponse response, object context)
500+
private JsonResponse PostProcess(JsonRequest request, JsonResponse response, object context)
535501
{
536502
if (externalPostProcessingHandler != null)
537503
{
@@ -548,10 +514,6 @@ private JsonResponse PostProcess(Action<JsonResponse> callback, JsonRequest requ
548514
response = new JsonResponse() { Error = ProcessException(request, new JsonRpcException(-32603, "Internal Error", ex)) };
549515
}
550516
}
551-
552-
if (callback != null)
553-
callback.Invoke(response);
554-
555517
return response;
556518
}
557519

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.