Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
LockedObjectsCommand.cs
1using System;
2using System.Text;
3using System.Threading.Tasks;
4using Waher.Content;
8using Waher.Things;
11
13{
18 {
24 : base(Report)
25 {
26 }
27
28 [Page(1, "Time", 150)]
29 [Header(24, "Threshold (ms):")]
30 [ToolTip(25, "Search for objects that have been locked for more time than this number of milliseconds.")]
31 public int Milliseconds = 10000;
32
33 [Page(1, "Time", 150)]
34 [Header(37, "Remove System References.")]
35 [ToolTip(38, "Remove System Refernces from stack traces in report.")]
36 public bool RemoveSystemReferences = true;
37
38 [Page(1, "Time", 150)]
39 [Header(41, "Only objects with waiting tasks.")]
40 [ToolTip(42, "Only include objects with tasks actively waiting for object to be released.")]
41 public bool OnlyIfWaitingTasks = true;
42
43 public override Task<string> GetNameAsync(Language Language)
44 {
45 return Language.GetStringAsync(typeof(SampleStatisticsCommand), 26, "Locked Objects...");
46 }
47
48 public override ICommand Copy()
49 {
51 {
52 Milliseconds = this.Milliseconds,
53 RemoveSystemReferences = this.RemoveSystemReferences
54 };
55 }
56
58 {
59 this.Execute(Query, Language);
60 return Task.CompletedTask;
61 }
62
63 private async void Execute(Query Query, Language Language)
64 {
65 try
66 {
67 await Query.Start();
68
69 string Title = await Language.GetStringAsync(typeof(LockedObjectsCommand), 27, "Locked Objects");
70 await Query.SetTitle(Title);
71 await Query.BeginSection(Title);
72
73 MultiReadSingleWriteObject[] Objects = Semaphores.FindLockedObjects(this.Milliseconds, this.OnlyIfWaitingTasks);
74 int i, c = Objects.Length;
75
76 if (c == 0)
77 await Query.NewObject(await Language.GetStringAsync(typeof(LockedObjectsCommand), 28, "No locked objects found past the threshold."));
78 else
79 {
80 await Query.NewTable("Objects",
81 await Language.GetStringAsync(typeof(LockedObjectsCommand), 29, "Objects"),
82 new Column("Index",
83 await Language.GetStringAsync(typeof(LockedObjectsCommand), 31, "Nr"),
84 null, null, null, null, ColumnAlignment.Right, null),
85 new Column("Owner",
86 await Language.GetStringAsync(typeof(LockedObjectsCommand), 30, "Owner"),
87 null, null, null, null, ColumnAlignment.Left, null),
88 new Column("QueueSize",
89 await Language.GetStringAsync(typeof(LockedObjectsCommand), 40, "Queued"),
90 null, null, null, null, ColumnAlignment.Right, null),
91 new Column("Token",
92 await Language.GetStringAsync(typeof(LockedObjectsCommand), 39, "Token"),
93 null, null, null, null, ColumnAlignment.Right, null),
94 new Column("NrReaders",
95 await Language.GetStringAsync(typeof(LockedObjectsCommand), 32, "#Readers"),
96 null, null, null, null, ColumnAlignment.Right, null),
97 new Column("IsWriting",
98 await Language.GetStringAsync(typeof(LockedObjectsCommand), 33, "Writing"),
99 null, null, null, null, ColumnAlignment.Center, null),
100 new Column("Time",
101 await Language.GetStringAsync(typeof(LockedObjectsCommand), 1, "Time"),
102 null, null, null, null, ColumnAlignment.Right, null));
103
104 Record[] Records = new Record[c];
106
107 for (i = 0; i < c; i++)
108 {
109 Obj = Objects[i];
110
111 string Unit = "ms";
112 double d = Obj.MillisecondsLocked;
113 byte NrDec = 0;
114
115 if (d >= 1000)
116 {
117 d /= 1000;
118 Unit = "s";
119 NrDec = 2;
120
121 if (d >= 60)
122 {
123 d /= 60;
124 Unit = "min";
125
126 if (d >= 60)
127 {
128 d /= 60;
129 Unit = "h";
130
131 if (d >= 24)
132 {
133 d /= 24;
134 Unit = "d";
135
136 if (d >= 7)
137 {
138 d /= 7;
139 Unit = "w";
140 }
141 }
142 }
143 }
144 }
145
146 Records[i] = new Record(
147 i + 1,
148 Obj.Owner?.ToString() ?? "NULL",
149 Obj.QueueSize,
150 Obj.Token,
151 Obj.NrReaders,
152 Obj.IsWriting,
153 CommonTypes.Encode(d, NrDec) + " " + Unit);
154
155 if (Obj.RecordStackTraces)
156 {
157 Title = (await Language.GetStringAsync(typeof(LockedObjectsCommand), 34, "Object %0%")).Replace("%0%", (i + 1).ToString());
158
159 if (!(Obj.Owner is null))
160 Title += ": " + Obj.Owner.ToString();
161
162 await Query.BeginSection(Title);
163
164 if (!string.IsNullOrEmpty(Obj.CreatorStackTrace))
165 {
166 await Query.BeginSection(await Language.GetStringAsync(typeof(LockedObjectsCommand), 35, "Creator"));
167 await Query.NewObject(this.ReportStackTrace(Obj.CreatorStackTrace));
168 await Query.EndSection();
169 }
170
171 if (!string.IsNullOrEmpty(Obj.LockStackTrace))
172 {
173 await Query.BeginSection(await Language.GetStringAsync(typeof(LockedObjectsCommand), 36, "Lock"));
174 await Query.NewObject(this.ReportStackTrace(Obj.LockStackTrace));
175 await Query.EndSection();
176 }
177
178 int j = 0;
179
180 foreach (string PendingStackTrace in Obj.QueuedStackTraces)
181 {
182 await Query.BeginSection((await Language.GetStringAsync(typeof(LockedObjectsCommand), 43, "Queued Stack Trace %0%")).Replace("%0%", (++j).ToString()));
183 await Query.NewObject(this.ReportStackTrace(PendingStackTrace));
184 await Query.EndSection();
185 }
186
187 await Query.EndSection();
188 }
189 }
190
191 await Query.NewRecords("Objects", Records);
192 await Query.TableDone("Objects");
193 }
194
195 await Query.EndSection();
196 }
197 catch (Exception ex)
198 {
199 await Query.LogMessage(ex);
200 }
201 finally
202 {
203 await Query.Done();
204 }
205 }
206
207 private MarkdownContent ReportStackTrace(string StackTrace)
208 {
209 StringBuilder sb = new StringBuilder();
210
211 sb.AppendLine("```");
212
213 if (this.RemoveSystemReferences)
214 {
215 string[] Rows = StackTrace.Split(CommonTypes.CRLF, StringSplitOptions.RemoveEmptyEntries);
216
217 foreach (string Row in Rows)
218 {
219 if (Row.TrimStart().StartsWith("at System."))
220 continue;
221
222 sb.AppendLine(Row);
223 }
224 }
225 else
226 sb.AppendLine(StackTrace.TrimEnd());
227
228 sb.AppendLine("```");
229
230 return new MarkdownContent(sb.ToString());
231 }
232 }
233}
Helps with parsing of commong data types.
Definition: CommonTypes.cs:15
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
Definition: CommonTypes.cs:596
static readonly char[] CRLF
Contains the CR LF character sequence.
Definition: CommonTypes.cs:19
Class that can be used to encapsulate Markdown to be returned from a Web Service, bypassing any encod...
ReportNode Report
Report node.
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
Represents an object that allows single concurrent writers but multiple concurrent readers....
string LockStackTrace
Stack trace from lock of object, if RecordStackTraces is true.
string[] QueuedStackTraces
Recorded stack traces waiting for access.
bool RecordStackTraces
If stack traces should be recorded when object is locked. Default value is true in DEBUG mode and fal...
long Token
Returns a token corresponding to the current lock. It is incremented at the start of a lock-cycle (wh...
double MillisecondsLocked
Number of milliseconds the object has been locked.
string CreatorStackTrace
Stack trace from creation of object, if RecordStackTraces is true.
Static class of application-wide semaphores that can be used to order access to editable objects.
Definition: Semaphores.cs:17
static MultiReadSingleWriteObject[] FindLockedObjects(int MillisecondsThreshold)
Returns an array of objects that have been locked for more time than the specified threshold.
Definition: Semaphores.cs:127
Abstract base class for commands executing a server administrator report.
override Task StartQueryExecutionAsync(Query Query, Language Language)
Starts the execution of a query.
override Task< string > GetNameAsync(Language Language)
Gets the displayable name of the command.
LockedObjectsCommand(ServerAdminReportNode Report)
Executes the HTTP Statistics report.
Abstract base class for server report nodes, requiring admin privileges to be seen and executed.
Defines a column in a table.
Definition: Column.cs:30
Class handling the reception of data from a query.
Definition: Query.cs:12
Task TableDone(string TableId)
Reports a table as being complete.
Definition: Query.cs:327
Task EndSection()
Ends a section. Each call to BeginSection(string) must be followed by a call to EndSection().
Definition: Query.cs:504
Task NewObject(object Object)
Reports a new object.
Definition: Query.cs:354
Task Start()
Starts query execution.
Definition: Query.cs:213
Task NewRecords(string TableId, params Record[] Records)
Reports a new set of records in a table.
Definition: Query.cs:300
Task BeginSection(string Header)
Begins a new section. Sections can be nested. Each call to BeginSection(string) must be followed by a...
Definition: Query.cs:483
Task NewTable(string TableId, string TableName, params Column[] Columns)
Defines a new table in the query output.
Definition: Query.cs:272
Task LogMessage(Exception Exception)
Logs an Exception as a query message.
Definition: Query.cs:381
async Task Done()
Query execution completed.
Definition: Query.cs:241
Task SetTitle(string Title)
Sets the title of the report.
Definition: Query.cs:430
Defines a record in a table.
Definition: Record.cs:9
Interface for commands.
Definition: ICommand.cs:32
delegate string ToString(IElement Element)
Delegate for callback methods that convert an element value to a string.
ColumnAlignment
Column alignment.
Definition: Column.cs:9