Skip to content

Commit 7577be0

Browse files
authored
Merge pull request Astn#78 from Astn/Cleanup
Removed redundant callback feature.
2 parents 321371f + 2832926 commit 7577be0

6 files changed

Lines changed: 87 additions & 242 deletions

File tree

AustinHarris.JsonRpcTestN/Test.cs

Lines 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
{

Json-Rpc/AustinHarris.JsonRpc.csproj

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
<DebugType>pdbonly</DebugType>
3636
<Optimize>true</Optimize>
3737
<OutputPath>bin\Release\</OutputPath>
38-
<DefineConstants>TRACE</DefineConstants>
38+
<DefineConstants>
39+
</DefineConstants>
3940
<ErrorReport>prompt</ErrorReport>
4041
<WarningLevel>4</WarningLevel>
4142
<Prefer32Bit>false</Prefer32Bit>
@@ -51,7 +52,8 @@
5152
<PlatformTarget>AnyCPU</PlatformTarget>
5253
<OutputPath>bin\Release\</OutputPath>
5354
<WarningLevel>4</WarningLevel>
54-
<Optimize>false</Optimize>
55+
<Optimize>true</Optimize>
56+
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
5557
</PropertyGroup>
5658
<ItemGroup>
5759
<Compile Include="Attributes.cs" />

Json-Rpc/Handler.cs

Lines 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)