github.com/iotexproject/iotex-core@v1.14.1-rc1/db/trie/mptrie/log.go (about) 1 package mptrie 2 3 import ( 4 "bufio" 5 "os" 6 7 "github.com/pkg/errors" 8 ) 9 10 var ( 11 enabledLogMptrie = false 12 logFile *os.File 13 logWriter *bufio.Writer 14 ) 15 16 type nodeType byte 17 type actionType byte 18 19 const ( 20 _nodeTypeLeaf nodeType = 'l' 21 _nodeTypeExtension nodeType = 'e' 22 _nodeTypeBranch nodeType = 'b' 23 24 _actionTypeSearch actionType = 's' 25 _actionTypeUpsert actionType = 'u' 26 _actionTypeDelete actionType = 'd' 27 _actionTypeNew actionType = 'n' 28 ) 29 30 // nodeEvent is the event of node 31 type nodeEvent struct { 32 NodeType nodeType 33 ActionType actionType 34 KeyLen uint8 35 Key []byte 36 PathLen uint8 37 Path []byte 38 ChildrenLen uint8 39 Children []byte 40 HashLen uint8 41 HashVal []byte 42 } 43 44 // Bytes returns the bytes of node event 45 func (e nodeEvent) Bytes() []byte { 46 b := make([]byte, 0, 1+1+1+e.KeyLen+1+e.PathLen+1+e.ChildrenLen+1+e.HashLen) 47 b = append(b, byte(e.NodeType)) 48 b = append(b, byte(e.ActionType)) 49 b = append(b, e.KeyLen) 50 b = append(b, e.Key...) 51 b = append(b, e.PathLen) 52 b = append(b, e.Path...) 53 b = append(b, e.ChildrenLen) 54 b = append(b, e.Children...) 55 b = append(b, e.HashLen) 56 b = append(b, e.HashVal...) 57 return b 58 } 59 60 // OpenLogDB open the log DB file 61 func OpenLogDB(dbPath string) error { 62 var err error 63 logFile, err = os.OpenFile(dbPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666) 64 if err != nil { 65 return err 66 } 67 logWriter = bufio.NewWriter(logFile) 68 enabledLogMptrie = true 69 return nil 70 } 71 72 // CloseLogDB close the log DB file 73 func CloseLogDB() error { 74 if !enabledLogMptrie { 75 return nil 76 } 77 if err := logWriter.Flush(); err != nil { 78 return err 79 } 80 return logFile.Close() 81 } 82 83 func logNode(nt nodeType, at actionType, n node, cli client) error { 84 if !enabledLogMptrie { 85 return nil 86 } 87 nodeKey, nodePath, nodeChildren, hashvalue, err := parseNode(n, cli) 88 if err != nil { 89 return err 90 } 91 event := nodeEvent{ 92 NodeType: nt, 93 ActionType: at, 94 KeyLen: uint8(len(nodeKey)), 95 Key: nodeKey, 96 PathLen: uint8(len(nodePath)), 97 Path: nodePath, 98 ChildrenLen: uint8(len(nodeChildren)), 99 Children: nodeChildren, 100 HashLen: uint8(len(hashvalue)), 101 HashVal: hashvalue, 102 } 103 // write event length 104 if err = logWriter.WriteByte(byte(len(event.Bytes()))); err != nil { 105 return err 106 } 107 // write event body 108 _, err = logWriter.Write(event.Bytes()) 109 return err 110 } 111 112 func parseNode(n node, cli client) (nodeKey, nodePath, nodeChildren, hashvalue []byte, err error) { 113 switch n := n.(type) { 114 case *leafNode: 115 nodeKey = n.key 116 hashvalue, err = n.cacheNode.Hash(cli) 117 case *extensionNode: 118 nodePath = n.path 119 hashvalue, err = n.cacheNode.Hash(cli) 120 case *branchNode: 121 nodeChildren = n.indices.List() 122 hashvalue, err = n.cacheNode.Hash(cli) 123 default: 124 err = errors.Errorf("unknown node type %T", n) 125 } 126 return 127 }