-
Notifications
You must be signed in to change notification settings - Fork 2k
/
SystemTarget.cs
164 lines (138 loc) · 6.62 KB
/
SystemTarget.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Orleans.CodeGeneration;
using Orleans.Runtime.Scheduler;
namespace Orleans.Runtime
{
/// <summary>
/// Base class for various system services, such as grain directory, reminder service, etc.
/// Made public for GrainSerive to inherit from it.
/// Can be turned to internal after a refactoring that would remove the inheritance relation.
/// </summary>
public abstract class SystemTarget : ISystemTarget, ISystemTargetBase, IInvokable, IGrainContext
{
private readonly GrainId grainId;
private GrainReference selfReference;
private IGrainMethodInvoker lastInvoker;
private Message running;
/// <summary>Silo address of the system target.</summary>
public SiloAddress Silo { get; }
internal ActivationAddress ActivationAddress { get; }
GrainId ISystemTargetBase.GrainId => grainId;
internal ActivationId ActivationId { get; set; }
private ISiloRuntimeClient runtimeClient;
private readonly ILogger timerLogger;
internal ISiloRuntimeClient RuntimeClient
{
get
{
if (this.runtimeClient == null)
throw new OrleansException(
$"{nameof(this.RuntimeClient)} has not been set on {this.GetType()}. Most likely, this means that the system target was not registered.");
return this.runtimeClient;
}
set { this.runtimeClient = value; }
}
private ExtensionInvoker extensionInvoker;
internal ExtensionInvoker ExtensionInvoker
{
get
{
this.lastInvoker = null;
return this.extensionInvoker ?? (this.extensionInvoker = new ExtensionInvoker());
}
}
IGrainReferenceRuntime ISystemTargetBase.GrainReferenceRuntime => this.RuntimeClient.GrainReferenceRuntime;
GrainReference IGrainContext.GrainReference => selfReference ??= GrainReference.FromGrainId(this.grainId, this.RuntimeClient.GrainReferenceRuntime, systemTargetSilo: this.Silo);
GrainId IGrainContext.GrainId => this.grainId;
IAddressable IGrainContext.GrainInstance => this;
ActivationId IGrainContext.ActivationId => this.ActivationId;
ActivationAddress IGrainContext.Address => this.ActivationAddress;
/// <summary>Only needed to make Reflection happy.</summary>
protected SystemTarget()
{
}
internal SystemTarget(GrainId grainId, SiloAddress silo, ILoggerFactory loggerFactory)
: this(grainId, silo, false, loggerFactory)
{
}
internal SystemTarget(GrainId grainId, SiloAddress silo, bool lowPriority, ILoggerFactory loggerFactory)
{
this.grainId = grainId;
this.Silo = silo;
this.ActivationAddress = ActivationAddress.GetAddress(this.Silo, this.grainId, this.ActivationId);
this.ActivationId = ActivationId.GetSystemActivation(grainId, silo);
this.IsLowPriority = lowPriority;
this.timerLogger = loggerFactory.CreateLogger<GrainTimer>();
}
public bool IsLowPriority { get; }
internal WorkItemGroup WorkItemGroup { get; set; }
IGrainMethodInvoker IInvokable.GetInvoker(GrainTypeManager typeManager, int interfaceId, string genericGrainType)
{
// Return previous cached invoker, if applicable
if (lastInvoker != null && interfaceId == lastInvoker.InterfaceId) // extension invoker returns InterfaceId==0, so this condition will never be true if an extension is installed
return lastInvoker;
if (extensionInvoker != null && extensionInvoker.IsExtensionInstalled(interfaceId))
{
// Shared invoker for all extensions installed on this target
lastInvoker = extensionInvoker;
}
else
{
// Find the specific invoker for this interface / grain type
lastInvoker = typeManager.GetInvoker(interfaceId, genericGrainType);
}
return lastInvoker;
}
internal void HandleNewRequest(Message request)
{
running = request;
this.RuntimeClient.Invoke(this, this, request).Ignore();
}
internal void HandleResponse(Message response)
{
running = response;
this.RuntimeClient.ReceiveResponse(response);
}
/// <summary>
/// Register a timer to send regular callbacks to this grain.
/// This timer will keep the current grain from being deactivated.
/// </summary>
/// <param name="asyncCallback"></param>
/// <param name="state"></param>
/// <param name="dueTime"></param>
/// <param name="period"></param>
/// <param name="name"></param>
/// <returns></returns>
public IDisposable RegisterTimer(Func<object, Task> asyncCallback, object state, TimeSpan dueTime, TimeSpan period, string name = null)
=> RegisterGrainTimer(asyncCallback, state, dueTime, period, name);
/// <summary>
/// Internal version of <see cref="RegisterTimer(Func{object, Task}, object, TimeSpan, TimeSpan, string)"/> that returns the inner IGrainTimer
/// </summary>
internal IGrainTimer RegisterGrainTimer(Func<object, Task> asyncCallback, object state, TimeSpan dueTime, TimeSpan period, string name = null)
{
var ctxt = RuntimeContext.CurrentGrainContext;
this.RuntimeClient.Scheduler.CheckSchedulingContextValidity(ctxt);
name = name ?? ctxt.GrainId + "Timer";
var timer = GrainTimer.FromTaskCallback(this.RuntimeClient.Scheduler, this.timerLogger, asyncCallback, state, dueTime, period, name);
timer.Start();
return timer;
}
/// <summary>Override of object.ToString()</summary>
public override string ToString()
{
return String.Format("[{0}SystemTarget: {1}{2}{3}]",
IsLowPriority ? "LowPriority" : string.Empty,
Silo,
this.grainId,
this.ActivationId);
}
/// <summary>Adds details about message currently being processed</summary>
internal string ToDetailedString()
{
return String.Format("{0} CurrentlyExecuting={1}", ToString(), running != null ? running.ToString() : "null");
}
bool IEquatable<IGrainContext>.Equals(IGrainContext other) => ReferenceEquals(this, other);
}
}