Line data Source code
1 : // Copyright 2024 The LevelDB-Go and Pebble Authors. All rights reserved. Use 2 : // of this source code is governed by a BSD-style license that can be found in 3 : // the LICENSE file. 4 : 5 : package treesteps 6 : 7 : import ( 8 : "fmt" 9 : "sync" 10 : "sync/atomic" 11 : ) 12 : 13 : type nodeState struct { 14 : recording *Recording 15 : depth int 16 : node Node 17 : name string 18 : 19 : // ops currently running for this node. 20 : ops []*Op 21 : } 22 : 23 : var mu struct { 24 : sync.Mutex 25 : 26 : recordingInProgress atomic.Bool 27 : nodeMap map[Node]*nodeState 28 : } 29 : 30 1 : func buildTree(n *nodeState) TreeNode { 31 1 : var t TreeNode 32 1 : info := n.node.TreeStepsNode() 33 1 : n.name = info.name 34 1 : t.Name = info.name 35 1 : t.Properties = info.properties 36 1 : if len(n.ops) > 0 { 37 1 : t.Ops = make([]string, len(n.ops)) 38 1 : for i := range t.Ops { 39 1 : t.Ops[i] = n.ops[i].details 40 1 : if n.ops[i].state != "" { 41 1 : t.Ops[i] += " " + n.ops[i].state 42 1 : } 43 : } 44 : } 45 1 : if n.depth < n.recording.maxTreeDepth { 46 1 : for i := range info.children { 47 1 : c := nodeStateLocked(n.recording, info.children[i]) 48 1 : c.depth = n.depth + 1 49 1 : t.Children = append(t.Children, buildTree(c)) 50 1 : } 51 1 : } else { 52 1 : for range info.children { 53 1 : t.Children = append(t.Children, TreeNode{Name: "..."}) 54 1 : } 55 : } 56 1 : return t 57 : } 58 : 59 1 : func nodeStateLocked(w *Recording, n Node) *nodeState { 60 1 : ns, ok := mu.nodeMap[n] 61 1 : if !ok { 62 1 : ns = &nodeState{recording: w, node: n} 63 1 : mu.nodeMap[n] = ns 64 1 : } else if w != ns.recording { 65 0 : panic(fmt.Sprintf("node %v part of multiple recordings", n)) 66 : } 67 1 : return ns 68 : }