xref: /petsc/src/sys/logging/handler/impls/nested/lognested.c (revision 6b2a052c0918f328006acf4a4a6053dc34c8a37e)
1b9321188SToby Isaac 
2b9321188SToby Isaac #include <petscviewer.h>
3b9321188SToby Isaac #include "lognested.h"
4b9321188SToby Isaac #include "xmlviewer.h"
5b9321188SToby Isaac 
6b9321188SToby Isaac PETSC_INTERN PetscErrorCode PetscLogHandlerNestedSetThreshold(PetscLogHandler h, PetscLogDouble newThresh, PetscLogDouble *oldThresh)
7b9321188SToby Isaac {
8b9321188SToby Isaac   PetscLogHandler_Nested nested = (PetscLogHandler_Nested)h->data;
9b9321188SToby Isaac 
10b9321188SToby Isaac   PetscFunctionBegin;
11b9321188SToby Isaac   if (oldThresh) *oldThresh = nested->threshold;
12b9321188SToby Isaac   if (newThresh == (PetscLogDouble)PETSC_DECIDE) newThresh = 0.01;
13b9321188SToby Isaac   if (newThresh == (PetscLogDouble)PETSC_DEFAULT) newThresh = 0.01;
14b9321188SToby Isaac   nested->threshold = PetscMax(newThresh, 0.0);
15b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
16b9321188SToby Isaac }
17b9321188SToby Isaac 
18b9321188SToby Isaac static PetscErrorCode PetscLogEventGetNestedEvent(PetscLogHandler h, PetscLogEvent e, PetscLogEvent *nested_event)
19b9321188SToby Isaac {
20b9321188SToby Isaac   PetscLogHandler_Nested nested = (PetscLogHandler_Nested)h->data;
21b9321188SToby Isaac   NestedIdPair           key;
22b9321188SToby Isaac   PetscHashIter          iter;
23b9321188SToby Isaac   PetscBool              missing;
24b9321188SToby Isaac   PetscLogState          state;
25b9321188SToby Isaac 
26b9321188SToby Isaac   PetscFunctionBegin;
27b9321188SToby Isaac   PetscCall(PetscLogHandlerGetState(h, &state));
28*6b2a052cSToby Isaac   PetscCall(PetscIntStackTop(nested->nested_stack, &(key.root)));
29b9321188SToby Isaac   key.leaf = NestedIdFromEvent(e);
30b9321188SToby Isaac   PetscCall(PetscNestedHashPut(nested->pair_map, key, &iter, &missing));
31b9321188SToby Isaac   if (missing) {
32b9321188SToby Isaac     // register a new nested event
33b9321188SToby Isaac     char              name[BUFSIZ];
34b9321188SToby Isaac     PetscLogEventInfo event_info;
35b9321188SToby Isaac     PetscLogEventInfo nested_event_info;
36b9321188SToby Isaac 
37b9321188SToby Isaac     PetscCall(PetscLogStateEventGetInfo(state, e, &event_info));
38b9321188SToby Isaac     PetscCall(PetscLogStateEventGetInfo(nested->state, key.root, &nested_event_info));
39b9321188SToby Isaac     PetscCall(PetscSNPrintf(name, sizeof(name) - 1, "%s;%s", nested_event_info.name, event_info.name));
40b9321188SToby Isaac     PetscCall(PetscLogStateEventRegister(nested->state, name, event_info.classid, nested_event));
41b9321188SToby Isaac     PetscCall(PetscNestedHashIterSet(nested->pair_map, iter, *nested_event));
42b9321188SToby Isaac   } else {
43b9321188SToby Isaac     PetscCall(PetscNestedHashIterGet(nested->pair_map, iter, nested_event));
44b9321188SToby Isaac   }
45b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
46b9321188SToby Isaac }
47b9321188SToby Isaac 
48b9321188SToby Isaac static PetscErrorCode PetscLogStageGetNestedEvent(PetscLogHandler h, PetscLogStage stage, PetscLogEvent *nested_event)
49b9321188SToby Isaac {
50b9321188SToby Isaac   PetscLogHandler_Nested nested = (PetscLogHandler_Nested)h->data;
51b9321188SToby Isaac   NestedIdPair           key;
52b9321188SToby Isaac   PetscHashIter          iter;
53b9321188SToby Isaac   PetscBool              missing;
54b9321188SToby Isaac   PetscLogState          state;
55b9321188SToby Isaac 
56b9321188SToby Isaac   PetscFunctionBegin;
57b9321188SToby Isaac   PetscCall(PetscLogHandlerGetState(h, &state));
58*6b2a052cSToby Isaac   PetscCall(PetscIntStackTop(nested->nested_stack, &(key.root)));
59b9321188SToby Isaac   key.leaf = NestedIdFromStage(stage);
60b9321188SToby Isaac   PetscCall(PetscNestedHashPut(nested->pair_map, key, &iter, &missing));
61b9321188SToby Isaac   if (missing) {
62b9321188SToby Isaac     PetscLogStageInfo stage_info;
63b9321188SToby Isaac     char              name[BUFSIZ];
64b9321188SToby Isaac 
65b9321188SToby Isaac     PetscCall(PetscLogStateStageGetInfo(state, stage, &stage_info));
66b9321188SToby Isaac     if (key.root >= 0) {
67b9321188SToby Isaac       PetscLogEventInfo nested_event_info;
68b9321188SToby Isaac 
69b9321188SToby Isaac       PetscCall(PetscLogStateEventGetInfo(nested->state, key.root, &nested_event_info));
70b9321188SToby Isaac       PetscCall(PetscSNPrintf(name, sizeof(name) - 1, "%s;%s", nested_event_info.name, stage_info.name));
71b9321188SToby Isaac     } else {
72b9321188SToby Isaac       PetscCall(PetscSNPrintf(name, sizeof(name) - 1, "%s", stage_info.name));
73b9321188SToby Isaac     }
74b9321188SToby Isaac     PetscCall(PetscLogStateEventRegister(nested->state, name, nested->nested_stage_id, nested_event));
75b9321188SToby Isaac     PetscCall(PetscNestedHashIterSet(nested->pair_map, iter, *nested_event));
76b9321188SToby Isaac   } else {
77b9321188SToby Isaac     PetscCall(PetscNestedHashIterGet(nested->pair_map, iter, nested_event));
78b9321188SToby Isaac   }
79b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
80b9321188SToby Isaac }
81b9321188SToby Isaac 
82*6b2a052cSToby Isaac static PetscErrorCode PetscLogNestedFindNestedId(PetscLogHandler h, NestedId orig_id, PetscInt *pop_count)
83*6b2a052cSToby Isaac {
84*6b2a052cSToby Isaac   PetscLogHandler_Nested nested = (PetscLogHandler_Nested)h->data;
85*6b2a052cSToby Isaac   PetscInt               count, i;
86*6b2a052cSToby Isaac 
87*6b2a052cSToby Isaac   PetscFunctionBegin;
88*6b2a052cSToby Isaac   // stop before zero cause there is a null event at the bottom of the stack
89*6b2a052cSToby Isaac   for (i = nested->orig_stack->top, count = 0; i > 0; i--) {
90*6b2a052cSToby Isaac     count++;
91*6b2a052cSToby Isaac     if (nested->orig_stack->stack[i] == orig_id) break;
92*6b2a052cSToby Isaac   }
93*6b2a052cSToby Isaac   *pop_count = count;
94*6b2a052cSToby Isaac   if (count == 1) PetscFunctionReturn(PETSC_SUCCESS); // Normal function, just the top of the stack is being popped.
95*6b2a052cSToby Isaac   if (orig_id > 0) {
96*6b2a052cSToby Isaac     PetscLogEvent     event_id = NestedIdToEvent(orig_id);
97*6b2a052cSToby Isaac     PetscLogState     state;
98*6b2a052cSToby Isaac     PetscLogEventInfo event_info;
99*6b2a052cSToby Isaac 
100*6b2a052cSToby Isaac     PetscCall(PetscLogHandlerGetState(h, &state));
101*6b2a052cSToby Isaac     PetscCall(PetscLogStateEventGetInfo(state, event_id, &event_info));
102*6b2a052cSToby Isaac     PetscCheck(i > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Tried to end event %s, but it is not in the event stack\n", event_info.name);
103*6b2a052cSToby Isaac   } else {
104*6b2a052cSToby Isaac     PetscLogStage     stage_id = NestedIdToStage(orig_id);
105*6b2a052cSToby Isaac     PetscLogState     state;
106*6b2a052cSToby Isaac     PetscLogStageInfo stage_info;
107*6b2a052cSToby Isaac 
108*6b2a052cSToby Isaac     PetscCall(PetscLogHandlerGetState(h, &state));
109*6b2a052cSToby Isaac     PetscCall(PetscLogStateStageGetInfo(state, stage_id, &stage_info));
110*6b2a052cSToby Isaac     PetscCheck(i > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Tried to pop stage %s, but it is not in the stage stack\n", stage_info.name);
111*6b2a052cSToby Isaac   }
112*6b2a052cSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
113*6b2a052cSToby Isaac }
114*6b2a052cSToby Isaac 
115b9321188SToby Isaac static PetscErrorCode PetscLogNestedCheckNested(PetscLogHandler h, NestedId leaf, PetscLogEvent nested_event)
116b9321188SToby Isaac {
117b9321188SToby Isaac   PetscLogHandler_Nested nested = (PetscLogHandler_Nested)h->data;
118b9321188SToby Isaac   NestedIdPair           key;
119b9321188SToby Isaac   NestedId               val;
120b9321188SToby Isaac 
121b9321188SToby Isaac   PetscFunctionBegin;
122*6b2a052cSToby Isaac   PetscCall(PetscIntStackTop(nested->nested_stack, &(key.root)));
123b9321188SToby Isaac   key.leaf = leaf;
124b9321188SToby Isaac   PetscCall(PetscNestedHashGet(nested->pair_map, key, &val));
125b9321188SToby Isaac   PetscCheck(val == nested_event, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Logging events and stages are not nested, nested logging cannot be used");
126b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
127b9321188SToby Isaac }
128b9321188SToby Isaac 
129b9321188SToby Isaac static PetscErrorCode PetscLogHandlerEventBegin_Nested(PetscLogHandler h, PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
130b9321188SToby Isaac {
131b9321188SToby Isaac   PetscLogHandler_Nested nested = (PetscLogHandler_Nested)h->data;
132b9321188SToby Isaac   PetscLogEvent          nested_event;
133b9321188SToby Isaac 
134b9321188SToby Isaac   PetscFunctionBegin;
135b9321188SToby Isaac   PetscCall(PetscLogEventGetNestedEvent(h, e, &nested_event));
136b9321188SToby Isaac   PetscCall(PetscLogHandlerEventBegin(nested->handler, nested_event, o1, o2, o3, o4));
137*6b2a052cSToby Isaac   PetscCall(PetscIntStackPush(nested->nested_stack, nested_event));
138*6b2a052cSToby Isaac   PetscCall(PetscIntStackPush(nested->orig_stack, NestedIdFromEvent(e)));
139*6b2a052cSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
140*6b2a052cSToby Isaac }
141*6b2a052cSToby Isaac 
142*6b2a052cSToby Isaac static PetscErrorCode PetscLogHandlerNestedEventEnd(PetscLogHandler h, NestedId id, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
143*6b2a052cSToby Isaac {
144*6b2a052cSToby Isaac   PetscLogHandler_Nested nested = (PetscLogHandler_Nested)h->data;
145*6b2a052cSToby Isaac   PetscInt               pop_count;
146*6b2a052cSToby Isaac 
147*6b2a052cSToby Isaac   PetscFunctionBegin;
148*6b2a052cSToby Isaac   PetscCall(PetscLogNestedFindNestedId(h, id, &pop_count));
149*6b2a052cSToby Isaac   for (PetscInt c = 0; c < pop_count; c++) {
150*6b2a052cSToby Isaac     PetscLogEvent nested_event;
151*6b2a052cSToby Isaac     PetscLogEvent nested_id;
152*6b2a052cSToby Isaac 
153*6b2a052cSToby Isaac     PetscCall(PetscIntStackPop(nested->nested_stack, &nested_event));
154*6b2a052cSToby Isaac     PetscCall(PetscIntStackPop(nested->orig_stack, &nested_id));
155*6b2a052cSToby Isaac     if (PetscDefined(USE_DEBUG)) PetscCall(PetscLogNestedCheckNested(h, nested_id, nested_event));
156*6b2a052cSToby Isaac     if ((pop_count > 1) && (c + 1 < pop_count)) {
157*6b2a052cSToby Isaac       if (nested_id > 0) {
158*6b2a052cSToby Isaac         PetscLogEvent     event_id = NestedIdToEvent(nested_id);
159*6b2a052cSToby Isaac         PetscLogState     state;
160*6b2a052cSToby Isaac         PetscLogEventInfo event_info;
161*6b2a052cSToby Isaac 
162*6b2a052cSToby Isaac         PetscCall(PetscLogHandlerGetState(h, &state));
163*6b2a052cSToby Isaac         PetscCall(PetscLogStateEventGetInfo(state, event_id, &event_info));
164*6b2a052cSToby Isaac         PetscCall(PetscInfo(h, "Log event %s wasn't ended, ending it to maintain stack property for nested log handler\n", event_info.name));
165*6b2a052cSToby Isaac       }
166*6b2a052cSToby Isaac     }
167*6b2a052cSToby Isaac     PetscCall(PetscLogHandlerEventEnd(nested->handler, nested_event, o1, o2, o3, o4));
168*6b2a052cSToby Isaac   }
169b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
170b9321188SToby Isaac }
171b9321188SToby Isaac 
172b9321188SToby Isaac static PetscErrorCode PetscLogHandlerEventEnd_Nested(PetscLogHandler h, PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
173b9321188SToby Isaac {
174b9321188SToby Isaac   PetscFunctionBegin;
175*6b2a052cSToby Isaac   PetscCall(PetscLogHandlerNestedEventEnd(h, NestedIdFromEvent(e), o1, o2, o3, o4));
176b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
177b9321188SToby Isaac }
178b9321188SToby Isaac 
179b9321188SToby Isaac static PetscErrorCode PetscLogHandlerEventSync_Nested(PetscLogHandler h, PetscLogEvent e, MPI_Comm comm)
180b9321188SToby Isaac {
181b9321188SToby Isaac   PetscLogHandler_Nested nested = (PetscLogHandler_Nested)h->data;
182b9321188SToby Isaac   PetscLogEvent          nested_event;
183b9321188SToby Isaac 
184b9321188SToby Isaac   PetscFunctionBegin;
185b9321188SToby Isaac   PetscCall(PetscLogEventGetNestedEvent(h, e, &nested_event));
186b9321188SToby Isaac   PetscCall(PetscLogHandlerEventSync(nested->handler, nested_event, comm));
187b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
188b9321188SToby Isaac }
189b9321188SToby Isaac 
190b9321188SToby Isaac static PetscErrorCode PetscLogHandlerStagePush_Nested(PetscLogHandler h, PetscLogStage stage)
191b9321188SToby Isaac {
192b9321188SToby Isaac   PetscLogHandler_Nested nested = (PetscLogHandler_Nested)h->data;
193b9321188SToby Isaac   PetscLogEvent          nested_event;
194b9321188SToby Isaac 
195b9321188SToby Isaac   PetscFunctionBegin;
196b9321188SToby Isaac   if (nested->nested_stage_id == -1) PetscCall(PetscClassIdRegister("LogNestedStage", &nested->nested_stage_id));
197b9321188SToby Isaac   PetscCall(PetscLogStageGetNestedEvent(h, stage, &nested_event));
198b9321188SToby Isaac   PetscCall(PetscLogHandlerEventBegin(nested->handler, nested_event, NULL, NULL, NULL, NULL));
199*6b2a052cSToby Isaac   PetscCall(PetscIntStackPush(nested->nested_stack, nested_event));
200*6b2a052cSToby Isaac   PetscCall(PetscIntStackPush(nested->orig_stack, NestedIdFromStage(stage)));
201b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
202b9321188SToby Isaac }
203b9321188SToby Isaac 
204b9321188SToby Isaac static PetscErrorCode PetscLogHandlerStagePop_Nested(PetscLogHandler h, PetscLogStage stage)
205b9321188SToby Isaac {
206b9321188SToby Isaac   PetscFunctionBegin;
207*6b2a052cSToby Isaac   PetscCall(PetscLogHandlerNestedEventEnd(h, NestedIdFromStage(stage), NULL, NULL, NULL, NULL));
208b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
209b9321188SToby Isaac }
210b9321188SToby Isaac 
211b9321188SToby Isaac static PetscErrorCode PetscLogHandlerContextCreate_Nested(MPI_Comm comm, PetscLogHandler_Nested *nested_p)
212b9321188SToby Isaac {
213b9321188SToby Isaac   PetscLogStage          root_stage;
214b9321188SToby Isaac   PetscLogHandler_Nested nested;
215b9321188SToby Isaac 
216b9321188SToby Isaac   PetscFunctionBegin;
217b9321188SToby Isaac   PetscCall(PetscNew(nested_p));
218b9321188SToby Isaac   nested = *nested_p;
219b9321188SToby Isaac   PetscCall(PetscLogStateCreate(&nested->state));
220*6b2a052cSToby Isaac   PetscCall(PetscIntStackCreate(&nested->nested_stack));
221*6b2a052cSToby Isaac   PetscCall(PetscIntStackCreate(&nested->orig_stack));
222b9321188SToby Isaac   nested->nested_stage_id = -1;
223b9321188SToby Isaac   nested->threshold       = 0.01;
224b9321188SToby Isaac   PetscCall(PetscNestedHashCreate(&nested->pair_map));
225b9321188SToby Isaac   PetscCall(PetscLogHandlerCreate(comm, &nested->handler));
226294de794SToby Isaac   PetscCall(PetscLogHandlerSetType(nested->handler, PETSCLOGHANDLERDEFAULT));
227b9321188SToby Isaac   PetscCall(PetscLogHandlerSetState(nested->handler, nested->state));
228b9321188SToby Isaac   PetscCall(PetscLogStateStageRegister(nested->state, "", &root_stage));
229b9321188SToby Isaac   PetscAssert(root_stage == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "root stage not zero");
230b9321188SToby Isaac   PetscCall(PetscLogHandlerStagePush(nested->handler, root_stage));
231b9321188SToby Isaac   PetscCall(PetscLogStateStagePush(nested->state, root_stage));
232*6b2a052cSToby Isaac   PetscCall(PetscIntStackPush(nested->nested_stack, -1));
233*6b2a052cSToby Isaac   PetscCall(PetscIntStackPush(nested->orig_stack, -1));
234b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
235b9321188SToby Isaac }
236b9321188SToby Isaac 
237b9321188SToby Isaac static PetscErrorCode PetscLogHandlerObjectCreate_Nested(PetscLogHandler h, PetscObject obj)
238b9321188SToby Isaac {
239b9321188SToby Isaac   PetscClassId           classid;
240b9321188SToby Isaac   PetscInt               num_registered, num_nested_registered;
241b9321188SToby Isaac   PetscLogState          state;
242b9321188SToby Isaac   PetscLogHandler_Nested nested = (PetscLogHandler_Nested)h->data;
243b9321188SToby Isaac 
244b9321188SToby Isaac   PetscFunctionBegin;
245b9321188SToby Isaac   // register missing objects
246b9321188SToby Isaac   PetscCall(PetscObjectGetClassId(obj, &classid));
247b9321188SToby Isaac   PetscCall(PetscLogHandlerGetState(h, &state));
248b9321188SToby Isaac   PetscCall(PetscLogStateGetNumClasses(nested->state, &num_nested_registered));
249b9321188SToby Isaac   PetscCall(PetscLogStateGetNumClasses(state, &num_registered));
250b9321188SToby Isaac   for (PetscLogClass c = num_nested_registered; c < num_registered; c++) {
251b9321188SToby Isaac     PetscLogClassInfo class_info;
252b9321188SToby Isaac     PetscLogClass     nested_c;
253b9321188SToby Isaac 
254b9321188SToby Isaac     PetscCall(PetscLogStateClassGetInfo(state, c, &class_info));
255b9321188SToby Isaac     PetscCall(PetscLogStateClassRegister(nested->state, class_info.name, class_info.classid, &nested_c));
256b9321188SToby Isaac   }
257b9321188SToby Isaac   PetscCall(PetscLogHandlerObjectCreate(nested->handler, obj));
258b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
259b9321188SToby Isaac }
260b9321188SToby Isaac 
261b9321188SToby Isaac static PetscErrorCode PetscLogHandlerObjectDestroy_Nested(PetscLogHandler h, PetscObject obj)
262b9321188SToby Isaac {
263b9321188SToby Isaac   PetscLogHandler_Nested nested = (PetscLogHandler_Nested)h->data;
264b9321188SToby Isaac 
265b9321188SToby Isaac   PetscFunctionBegin;
266b9321188SToby Isaac   PetscCall(PetscLogHandlerObjectDestroy(nested->handler, obj));
267b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
268b9321188SToby Isaac }
269b9321188SToby Isaac 
270b9321188SToby Isaac static PetscErrorCode PetscLogHandlerDestroy_Nested(PetscLogHandler h)
271b9321188SToby Isaac {
272b9321188SToby Isaac   PetscLogHandler_Nested nested = (PetscLogHandler_Nested)h->data;
273b9321188SToby Isaac 
274b9321188SToby Isaac   PetscFunctionBegin;
275b9321188SToby Isaac   PetscCall(PetscLogStateStagePop(nested->state));
276b9321188SToby Isaac   PetscCall(PetscLogHandlerStagePop(nested->handler, 0));
277b9321188SToby Isaac   PetscCall(PetscLogStateDestroy(&nested->state));
278*6b2a052cSToby Isaac   PetscCall(PetscIntStackDestroy(nested->nested_stack));
279*6b2a052cSToby Isaac   PetscCall(PetscIntStackDestroy(nested->orig_stack));
280b9321188SToby Isaac   PetscCall(PetscNestedHashDestroy(&nested->pair_map));
281b9321188SToby Isaac   PetscCall(PetscLogHandlerDestroy(&nested->handler));
282b9321188SToby Isaac   PetscCall(PetscFree(nested));
283b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
284b9321188SToby Isaac }
285b9321188SToby Isaac 
286b9321188SToby Isaac static PetscErrorCode PetscLogNestedEventNodesOrderDepthFirst(PetscInt num_nodes, PetscInt parent, PetscNestedEventNode tree[], PetscInt *num_descendants)
287b9321188SToby Isaac {
288b9321188SToby Isaac   PetscInt node, start_loc;
289b9321188SToby Isaac   PetscFunctionBegin;
290b9321188SToby Isaac 
291b9321188SToby Isaac   node      = 0;
292b9321188SToby Isaac   start_loc = 0;
293b9321188SToby Isaac   while (node < num_nodes) {
294b9321188SToby Isaac     if (tree[node].parent == parent) {
295b9321188SToby Isaac       PetscInt             num_this_descendants = 0;
296b9321188SToby Isaac       PetscNestedEventNode tmp                  = tree[start_loc];
297b9321188SToby Isaac       tree[start_loc]                           = tree[node];
298b9321188SToby Isaac       tree[node]                                = tmp;
299b9321188SToby Isaac       PetscCall(PetscLogNestedEventNodesOrderDepthFirst(num_nodes - start_loc - 1, tree[start_loc].id, &tree[start_loc + 1], &num_this_descendants));
300b9321188SToby Isaac       tree[start_loc].num_descendants = num_this_descendants;
301b9321188SToby Isaac       *num_descendants += 1 + num_this_descendants;
302b9321188SToby Isaac       start_loc += 1 + num_this_descendants;
303b9321188SToby Isaac       node = start_loc;
304b9321188SToby Isaac     } else {
305b9321188SToby Isaac       node++;
306b9321188SToby Isaac     }
307b9321188SToby Isaac   }
308b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
309b9321188SToby Isaac }
310b9321188SToby Isaac 
311b9321188SToby Isaac static PetscErrorCode PetscLogNestedCreatePerfNodes(MPI_Comm comm, PetscLogHandler_Nested nested, PetscLogGlobalNames global_events, PetscNestedEventNode **tree_p, PetscEventPerfInfo **perf_p)
312b9321188SToby Isaac {
313b9321188SToby Isaac   PetscMPIInt           size;
314b9321188SToby Isaac   PetscInt              num_nodes;
315b9321188SToby Isaac   PetscInt              num_map_entries;
316b9321188SToby Isaac   PetscEventPerfInfo   *perf;
317b9321188SToby Isaac   NestedIdPair         *keys;
318b9321188SToby Isaac   NestedId             *vals;
319b9321188SToby Isaac   PetscInt              offset;
320b9321188SToby Isaac   PetscInt              num_descendants;
321b9321188SToby Isaac   PetscNestedEventNode *tree;
322b9321188SToby Isaac 
323b9321188SToby Isaac   PetscFunctionBegin;
324b9321188SToby Isaac   PetscCall(PetscLogGlobalNamesGetSize(global_events, NULL, &num_nodes));
325b9321188SToby Isaac   PetscCall(PetscCalloc1(num_nodes, &tree));
326b9321188SToby Isaac   for (PetscInt node = 0; node < num_nodes; node++) {
327b9321188SToby Isaac     tree[node].id = node;
328b9321188SToby Isaac     PetscCall(PetscLogGlobalNamesGlobalGetName(global_events, node, &tree[node].name));
329b9321188SToby Isaac     tree[node].parent = -1;
330b9321188SToby Isaac   }
331b9321188SToby Isaac   PetscCall(PetscNestedHashGetSize(nested->pair_map, &num_map_entries));
332b9321188SToby Isaac   PetscCall(PetscMalloc2(num_map_entries, &keys, num_map_entries, &vals));
333b9321188SToby Isaac   offset = 0;
334b9321188SToby Isaac   PetscCall(PetscNestedHashGetPairs(nested->pair_map, &offset, keys, vals));
335b9321188SToby Isaac   for (PetscInt k = 0; k < num_map_entries; k++) {
336b9321188SToby Isaac     NestedId root_local = keys[k].root;
337b9321188SToby Isaac     NestedId leaf_local = vals[k];
338b9321188SToby Isaac     PetscInt root_global;
339b9321188SToby Isaac     PetscInt leaf_global;
340b9321188SToby Isaac 
341b9321188SToby Isaac     PetscCall(PetscLogGlobalNamesLocalGetGlobal(global_events, leaf_local, &leaf_global));
342b9321188SToby Isaac     if (root_local >= 0) {
343b9321188SToby Isaac       PetscCall(PetscLogGlobalNamesLocalGetGlobal(global_events, root_local, &root_global));
344b9321188SToby Isaac       tree[leaf_global].parent = root_global;
345b9321188SToby Isaac     }
346b9321188SToby Isaac   }
347b9321188SToby Isaac   PetscCall(PetscFree2(keys, vals));
348b9321188SToby Isaac   PetscCallMPI(MPI_Comm_size(comm, &size));
349b9321188SToby Isaac   if (size > 1) { // get missing parents from other processes
350b9321188SToby Isaac     PetscInt *parents;
351b9321188SToby Isaac 
352b9321188SToby Isaac     PetscCall(PetscMalloc1(num_nodes, &parents));
353b9321188SToby Isaac     for (PetscInt node = 0; node < num_nodes; node++) parents[node] = tree[node].parent;
354b9321188SToby Isaac     PetscCall(MPIU_Allreduce(MPI_IN_PLACE, parents, num_nodes, MPIU_INT, MPI_MAX, comm));
355b9321188SToby Isaac     for (PetscInt node = 0; node < num_nodes; node++) tree[node].parent = parents[node];
356b9321188SToby Isaac     PetscCall(PetscFree(parents));
357b9321188SToby Isaac   }
358b9321188SToby Isaac 
359b9321188SToby Isaac   num_descendants = 0;
360b9321188SToby Isaac   PetscCall(PetscLogNestedEventNodesOrderDepthFirst(num_nodes, -1, tree, &num_descendants));
361b9321188SToby Isaac   PetscAssert(num_descendants == num_nodes, comm, PETSC_ERR_PLIB, "Failed tree ordering invariant");
362b9321188SToby Isaac 
363b9321188SToby Isaac   PetscCall(PetscCalloc1(num_nodes, &perf));
364c244758eSToby Isaac   for (PetscInt tree_node = 0; tree_node < num_nodes; tree_node++) {
365c244758eSToby Isaac     PetscInt global_id = tree[tree_node].id;
366b9321188SToby Isaac     PetscInt event_id;
367b9321188SToby Isaac 
368c244758eSToby Isaac     PetscCall(PetscLogGlobalNamesGlobalGetLocal(global_events, global_id, &event_id));
369b9321188SToby Isaac     if (event_id >= 0) {
370b9321188SToby Isaac       PetscEventPerfInfo *event_info;
371b9321188SToby Isaac 
372dff009beSToby Isaac       PetscCall(PetscLogHandlerGetEventPerfInfo(nested->handler, 0, event_id, &event_info));
373c244758eSToby Isaac       perf[tree_node] = *event_info;
374b9321188SToby Isaac     } else {
375c244758eSToby Isaac       PetscCall(PetscArrayzero(&perf[tree_node], 1));
376b9321188SToby Isaac     }
377b9321188SToby Isaac   }
378b9321188SToby Isaac   *tree_p = tree;
379b9321188SToby Isaac   *perf_p = perf;
380b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
381b9321188SToby Isaac }
382b9321188SToby Isaac 
383b9321188SToby Isaac static PetscErrorCode PetscLogHandlerView_Nested(PetscLogHandler handler, PetscViewer viewer)
384b9321188SToby Isaac {
385b9321188SToby Isaac   PetscLogHandler_Nested nested = (PetscLogHandler_Nested)handler->data;
386b9321188SToby Isaac   PetscNestedEventNode  *nodes;
387b9321188SToby Isaac   PetscEventPerfInfo    *perf;
388b9321188SToby Isaac   PetscLogGlobalNames    global_events;
389b9321188SToby Isaac   PetscNestedEventTree   tree;
390b9321188SToby Isaac   PetscViewerFormat      format;
391b9321188SToby Isaac   MPI_Comm               comm = PetscObjectComm((PetscObject)viewer);
392b9321188SToby Isaac 
393b9321188SToby Isaac   PetscFunctionBegin;
394b9321188SToby Isaac   PetscCall(PetscLogRegistryCreateGlobalEventNames(comm, nested->state->registry, &global_events));
395b9321188SToby Isaac   PetscCall(PetscLogNestedCreatePerfNodes(comm, nested, global_events, &nodes, &perf));
396b9321188SToby Isaac   tree.comm          = comm;
397b9321188SToby Isaac   tree.global_events = global_events;
398b9321188SToby Isaac   tree.perf          = perf;
399b9321188SToby Isaac   tree.nodes         = nodes;
400b9321188SToby Isaac   PetscCall(PetscViewerGetFormat(viewer, &format));
401b9321188SToby Isaac   if (format == PETSC_VIEWER_ASCII_XML) {
402b9321188SToby Isaac     PetscCall(PetscLogHandlerView_Nested_XML(nested, &tree, viewer));
403b9321188SToby Isaac   } else if (format == PETSC_VIEWER_ASCII_FLAMEGRAPH) {
404b9321188SToby Isaac     PetscCall(PetscLogHandlerView_Nested_Flamegraph(nested, &tree, viewer));
405b9321188SToby Isaac   } else SETERRQ(comm, PETSC_ERR_ARG_INCOMP, "No nested viewer for this format");
406b9321188SToby Isaac   PetscCall(PetscLogGlobalNamesDestroy(&global_events));
407b9321188SToby Isaac   PetscCall(PetscFree(tree.nodes));
408b9321188SToby Isaac   PetscCall(PetscFree(tree.perf));
409b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
410b9321188SToby Isaac }
411b9321188SToby Isaac 
412b9321188SToby Isaac /*MC
413294de794SToby Isaac   PETSCLOGHANDLERNESTED - PETSCLOGHANDLERNESTED = "nested" -  A `PetscLogHandler` that collects data for PETSc's
414b665b14eSToby Isaac   XML and flamegraph profiling log viewers.  A log handler of this type is created and started by
415b665b14eSToby Isaac   by `PetscLogNestedBegin()`.
416b9321188SToby Isaac 
417b9321188SToby Isaac   Level: developer
418b9321188SToby Isaac 
419b9321188SToby Isaac .seealso: [](ch_profiling), `PetscLogHandler`
420b9321188SToby Isaac M*/
421b9321188SToby Isaac 
422b9321188SToby Isaac PETSC_INTERN PetscErrorCode PetscLogHandlerCreate_Nested(PetscLogHandler handler)
423b9321188SToby Isaac {
424b9321188SToby Isaac   PetscFunctionBegin;
425b9321188SToby Isaac   PetscCall(PetscLogHandlerContextCreate_Nested(PetscObjectComm((PetscObject)handler), (PetscLogHandler_Nested *)&handler->data));
426b9321188SToby Isaac   handler->ops->destroy       = PetscLogHandlerDestroy_Nested;
427b9321188SToby Isaac   handler->ops->stagepush     = PetscLogHandlerStagePush_Nested;
428b9321188SToby Isaac   handler->ops->stagepop      = PetscLogHandlerStagePop_Nested;
429b9321188SToby Isaac   handler->ops->eventbegin    = PetscLogHandlerEventBegin_Nested;
430b9321188SToby Isaac   handler->ops->eventend      = PetscLogHandlerEventEnd_Nested;
431b9321188SToby Isaac   handler->ops->eventsync     = PetscLogHandlerEventSync_Nested;
432b9321188SToby Isaac   handler->ops->objectcreate  = PetscLogHandlerObjectCreate_Nested;
433b9321188SToby Isaac   handler->ops->objectdestroy = PetscLogHandlerObjectDestroy_Nested;
434b9321188SToby Isaac   handler->ops->view          = PetscLogHandlerView_Nested;
435b9321188SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
436b9321188SToby Isaac }
437