Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
ProcessorSource.cs
1using System;
3using System.Threading.Tasks;
4using Waher.Events;
10using Waher.Things;
12
13namespace Waher.Processors
14{
20 {
24 public const string SourceID = "Processors";
25
26 private static readonly Dictionary<string, ProcessorNode> nodes = new Dictionary<string, ProcessorNode>();
27 private static Root root = null;
28 private static ProcessorSource instance = null;
29
30 private DateTime lastChanged;
31
37 {
38 this.lastChanged = RuntimeSettings.Get(SourceID + ".LastChanged", DateTime.MinValue);
39 instance ??= this;
40 }
41
45 string IDataSource.SourceID => SourceID;
46
50 public IEnumerable<IDataSource> ChildSources => null;
51
55 public bool HasChildren => false;
56
60 public DateTime LastChanged
61 {
62 get => this.lastChanged;
63 internal set
64 {
65 if (this.lastChanged != value)
66 {
67 this.lastChanged = value;
68 Task _ = RuntimeSettings.SetAsync("ProcessorSource.LastChanged", value);
69 }
70 }
71 }
72
78 public Task<string> GetNameAsync(Language Language)
79 {
80 return Language.GetStringAsync(typeof(ProcessorSource), 13, "Processors");
81 }
82
88 public async Task<INode> GetNodeAsync(IThingReference NodeRef)
89 {
90 return await GetNode(NodeRef);
91 }
92
98 public static Task<ProcessorNode> GetNode(string NodeId)
99 {
100 return GetNode(new ThingReference(NodeId, SourceID));
101 }
102
108 public static async Task<ProcessorNode> GetNode(IThingReference NodeRef)
109 {
110 if (NodeRef is null || NodeRef.SourceId != SourceID || !string.IsNullOrEmpty(NodeRef.Partition))
111 return null;
112
113 lock (nodes)
114 {
115 if (nodes.TryGetValue(NodeRef.NodeId, out ProcessorNode Node))
116 return Node;
117 }
118
119 foreach (ProcessorNode Node2 in await Database.Find<ProcessorNode>(new FilterFieldEqualTo("NodeId", NodeRef.NodeId)))
120 {
121 lock (nodes)
122 {
123 if (nodes.TryGetValue(NodeRef.NodeId, out ProcessorNode Node))
124 return Node;
125 else
126 {
127 nodes[NodeRef.NodeId] = Node2;
128 return Node2;
129 }
130 }
131 }
132
133 return null;
134 }
135
136 internal static ProcessorNode RegisterNode(ProcessorNode Node)
137 {
138 if (Node.SourceId == SourceID && string.IsNullOrEmpty(Node.Partition))
139 {
140 lock (nodes)
141 {
142 if (nodes.TryGetValue(Node.NodeId, out ProcessorNode Node2))
143 return Node2;
144 else
145 {
146 nodes[Node.NodeId] = Node;
147 return Node;
148 }
149 }
150 }
151 else
152 return Node;
153 }
154
155 internal static ProcessorNode RegisterNewNodeId(ProcessorNode Node, string OldId)
156 {
157 if (Node.SourceId != SourceID || !string.IsNullOrEmpty(Node.Partition))
158 return Node;
159
160 lock (nodes)
161 {
162 if (!nodes.TryGetValue(OldId, out ProcessorNode Node2) || Node2 != Node)
163 return Node;
164
165 if (nodes.TryGetValue(Node.NodeId, out Node2))
166 return Node2;
167
168 nodes.Remove(OldId);
169 nodes[Node.NodeId] = Node;
170
171 return Node;
172 }
173 }
174
175 internal static void UnregisterNode(ProcessorNode Node)
176 {
177 if (Node.SourceId == SourceID && string.IsNullOrEmpty(Node.Partition))
178 {
179 lock (nodes)
180 {
181 if (nodes.TryGetValue(Node.NodeId, out ProcessorNode Node2) && Node == Node2)
182 nodes.Remove(Node.NodeId);
183 }
184 }
185 }
186
192 public Task<bool> CanViewAsync(RequestOrigin Caller)
193 {
194 return Task.FromResult(Caller.HasPrivilege("Source." + SourceID + ".View"));
195 }
196
200 public IEnumerable<INode> RootNodes
201 {
202 get
203 {
204 if (root is null)
205 LoadRoot().Wait();
206
207 return new INode[] { root };
208 }
209 }
210
214 public static Root Root
215 {
216 get
217 {
218 if (root is null)
219 LoadRoot().Wait();
220
221 return root;
222 }
223 }
224
225 private static async Task LoadRoot()
226 {
227 Root Result = null;
228
229 foreach (ProcessorNode Node in await Database.Find<ProcessorNode>(new FilterFieldEqualTo("ParentId", Guid.Empty)))
230 {
231 if (Node is Root Root)
232 {
233 if (Result is null)
234 Result = Root;
235 else
236 await Database.Delete(Node);
237 }
238 }
239
240 if (Result is null)
241 {
242 Result = new Root()
243 {
244 NodeId = await (await Translator.GetDefaultLanguageAsync()).GetStringAsync(typeof(Root), 1, "Root")
245 };
246
247 await Database.Insert(Result);
248
250 await NewEvent(new NodeAdded()
251 {
253 NodeType = Result.GetType().FullName,
254 Sniffable = false,
255 DisplayName = await Result.GetTypeNameAsync(Language),
256 HasChildren = Result.HasChildren,
257 ChildrenOrdered = Result.ChildrenOrdered,
258 IsReadable = Result.IsReadable,
259 IsControllable = Result.IsControllable,
260 HasCommands = Result.HasCommands,
261 ParentId = string.Empty,
262 ParentPartition = string.Empty,
263 Updated = Result.Updated,
264 State = Result.State,
265 NodeId = Result.NodeId,
266 Partition = Result.Partition,
267 LogId = NodeAdded.EmptyIfSame(Result.LogId, Result.NodeId),
268 LocalId = NodeAdded.EmptyIfSame(Result.LocalId, Result.NodeId),
269 SourceId = Result.SourceId,
270 Timestamp = DateTime.UtcNow
271 });
272 }
273
274 lock (nodes)
275 {
276 nodes[Result.NodeId] = Result;
277 }
278
279 root = Result;
280 }
281
287 public static async Task<int> DeleteOldEvents(TimeSpan MaxAge)
288 {
289 if (MaxAge <= TimeSpan.Zero)
290 throw new ArgumentException("Age must be positive.", nameof(MaxAge));
291
292 DateTime Limit = DateTime.Now.Subtract(MaxAge);
293 int NrEvents = await Database.Delete<SourceEvent>(new FilterAnd(
294 new FilterFieldEqualTo("SourceId", SourceID),
295 new FilterFieldLesserOrEqualTo("Timestamp", Limit)));
296
297 if (NrEvents > 0)
298 {
299 KeyValuePair<string, object>[] Tags = new KeyValuePair<string, object>[]
300 {
301 new KeyValuePair<string, object>("Limit", Limit),
302 new KeyValuePair<string, object>("NrEvents", NrEvents)
303 };
304
305 if (NrEvents == 1)
306 Log.Informational("Deleting 1 processor event from the database.", SourceID, Tags);
307 else
308 Log.Informational("Deleting " + NrEvents.ToString() + " processor events from the database.", SourceID, Tags);
309 }
310
311 return NrEvents;
312 }
313
317 public event EventHandlerAsync<SourceEvent> OnEvent = null;
318
319 internal static async Task NewEvent(SourceEvent Event)
320 {
321 await Database.Insert(Event);
322 await (instance?.OnEvent?.Raise(instance, Event) ?? Task.CompletedTask);
323 }
324
329 public static async Task<int> DeleteOrphans()
330 {
331 int Result = 0;
332
333 foreach (ProcessorNode Node in await Database.Find<ProcessorNode>())
334 {
335 if (Node.ParentId == Guid.Empty)
336 continue;
337
339 if (ParentNode is null)
340 {
341 await Database.Delete(Node);
342 Result++;
343
344 lock (nodes)
345 {
346 nodes.Remove(Node.NodeId);
347 }
348 }
349 }
350
351 return Result;
352 }
353 }
354}
Class representing an event.
Definition: Event.cs:11
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:14
static void Informational(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an informational event.
Definition: Log.cs:344
Static interface for database persistence. In order to work, a database provider has to be assigned t...
Definition: Database.cs:21
static async Task Delete(object Object)
Deletes an object in the database.
Definition: Database.cs:1291
static Task< IEnumerable< object > > Find(string Collection, params string[] SortOrder)
Finds objects in a given collection.
Definition: Database.cs:238
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
Definition: Database.cs:97
static Task< object > TryLoadObject(string CollectionName, object ObjectId)
Tries to load an object given its Object ID ObjectId and its collection name CollectionName .
Definition: Database.cs:1838
This filter selects objects that conform to all child-filters provided.
Definition: FilterAnd.cs:10
This filter selects objects that have a named field equal to a given value.
This filter selects objects that have a named field lesser or equal to a given value.
Class for the root node of the Processors data source.
Definition: Root.cs:11
override Task< string > GetTypeNameAsync(Language Language)
Gets the type name of the node.
Definition: Root.cs:25
Base class for all processor nodes.
async Task< Parameter[]> GetDisplayableParameterAraryAsync(Language Language, RequestOrigin Caller)
Gets displayable parameters.
string SourceId
Optional ID of source containing node.
NodeState State
Current overall state of the node.
virtual bool HasCommands
If the node has registered commands or not.
virtual bool IsReadable
If the node can be read.
virtual bool ChildrenOrdered
If the children of the node have an intrinsic order (true), or if the order is not important (false).
virtual string LocalId
If provided, an ID for the node, but unique locally between siblings. Can be null,...
virtual bool IsControllable
If the node can be controlled.
virtual string LogId
If provided, an ID for the node, as it would appear or be used in system logs. Can be null,...
bool HasChildren
If the source has any child sources.
Guid ParentId
Object ID of parent node in persistence layer.
DateTime Updated
When node was last updated. If it has not been updated, value will be DateTime.MinValue.
string Partition
Optional partition in which the Node ID is unique.
Defines the Processors data source. This data source contains a tree structure of processor of nodes
Task< string > GetNameAsync(Language Language)
Gets the name of data source.
static async Task< int > DeleteOrphans()
Deletes orphaned nodes in the metering topology source.
Task< bool > CanViewAsync(RequestOrigin Caller)
If the data source is visible to the caller.
static Task< ProcessorNode > GetNode(string NodeId)
Gets a node from the Metering Topology
DateTime LastChanged
When the source was last updated.
static async Task< ProcessorNode > GetNode(IThingReference NodeRef)
Gets a node from the Metering Topology
IEnumerable< IDataSource > ChildSources
Child sources. If no child sources are available, null is returned.
async Task< INode > GetNodeAsync(IThingReference NodeRef)
Gets the node, given a reference to it.
EventHandlerAsync< SourceEvent > OnEvent
Event raised when a data source event has been raised.
bool HasChildren
If the source has any child sources.
const string SourceID
Source ID for the processors data source.
ProcessorSource()
Defines the Metering Topology data source. This data source contains a tree structure of persistent r...
static async Task< int > DeleteOldEvents(TimeSpan MaxAge)
Deletes old data source events.
IEnumerable< INode > RootNodes
Root node references. If no root nodes are available, null is returned.
Contains information about a language.
Definition: Language.cs:17
Task< string > GetStringAsync(Type Type, int Id, string Default)
Gets the string value of a string ID. If no such string exists, a string is created with the default ...
Definition: Language.cs:209
Basic access point for runtime language localization.
Definition: Translator.cs:16
static async Task< Language > GetDefaultLanguageAsync()
Gets the default language.
Definition: Translator.cs:223
Static class managing persistent settings.
static string Get(string Key, string DefaultValue)
Gets a string-valued setting.
static async Task< bool > SetAsync(string Key, string Value)
Sets a string-valued setting.
Tokens available in request.
Definition: RequestOrigin.cs:9
static readonly RequestOrigin Empty
Empty request origin.
bool HasPrivilege(string Privilege)
If the origin has a given privilege.
static string EmptyIfSame(string Id1, string Id2)
Returns Id1 if different, string.Empty if the same.
Definition: NodeAdded.cs:93
Abstract base class for all data source events.
Definition: SourceEvent.cs:13
Contains a reference to a thing
Interface for datasources that are published through the concentrator interface.
Definition: IDataSource.cs:14
Interface for nodes that are published through the concentrator interface.
Definition: INode.cs:49
Interface for thing references.
string Partition
Optional partition in which the Node ID is unique.
string SourceId
Optional ID of source containing node.
Definition: ImplTypes.g.cs:58