github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/core/tx_journal.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2017 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package core 26 27 import ( 28 "errors" 29 "io" 30 "os" 31 32 "github.com/ethereum/go-ethereum/common" 33 "github.com/ethereum/go-ethereum/core/types" 34 "github.com/ethereum/go-ethereum/log" 35 "github.com/ethereum/go-ethereum/rlp" 36 ) 37 38 //如果试图插入事务,则返回errnoaactivejournal 39 //进入日志,但当前没有打开该文件。 40 var errNoActiveJournal = errors.New("no active journal") 41 42 //devnull是一个只丢弃写入其中的任何内容的writecloser。它的 43 //目标是允许事务日记帐在以下情况下写入假日记帐: 44 //由于没有文件,在启动时加载事务,但不打印警告 45 //正在准备写入。 46 type devNull struct{} 47 48 func (*devNull) Write(p []byte) (n int, err error) { return len(p), nil } 49 func (*devNull) Close() error { return nil } 50 51 //txjournal是一个旋转的事务日志,目的是在本地存储 52 //创建的事务允许未执行的事务在节点重新启动后继续存在。 53 type txJournal struct { 54 path string //存储事务的文件系统路径 55 writer io.WriteCloser //将新事务写入的输出流 56 } 57 58 //newtxjournal创建新的交易日记帐到 59 func newTxJournal(path string) *txJournal { 60 return &txJournal{ 61 path: path, 62 } 63 } 64 65 //LOAD分析事务日志从磁盘转储,将其内容加载到 66 //指定的池。 67 func (journal *txJournal) load(add func([]*types.Transaction) []error) error { 68 //如果日志文件根本不存在,则跳过分析 69 if _, err := os.Stat(journal.path); os.IsNotExist(err) { 70 return nil 71 } 72 //打开日记帐以加载任何过去的交易记录 73 input, err := os.Open(journal.path) 74 if err != nil { 75 return err 76 } 77 defer input.Close() 78 79 //暂时丢弃任何日志添加(加载时不要重复添加) 80 journal.writer = new(devNull) 81 defer func() { journal.writer = nil }() 82 83 //将日记帐中的所有交易记录插入池 84 stream := rlp.NewStream(input, 0) 85 total, dropped := 0, 0 86 87 //创建一个方法来加载有限批事务并 88 //适当的进度计数器。然后使用此方法加载 89 //以小批量记录交易。 90 loadBatch := func(txs types.Transactions) { 91 for _, err := range add(txs) { 92 if err != nil { 93 log.Debug("Failed to add journaled transaction", "err", err) 94 dropped++ 95 } 96 } 97 } 98 var ( 99 failure error 100 batch types.Transactions 101 ) 102 for { 103 //分析下一个事务并在出错时终止 104 tx := new(types.Transaction) 105 if err = stream.Decode(tx); err != nil { 106 if err != io.EOF { 107 failure = err 108 } 109 if batch.Len() > 0 { 110 loadBatch(batch) 111 } 112 break 113 } 114 //已分析新事务,排队等待稍后,如果达到threnshold,则导入 115 total++ 116 117 if batch = append(batch, tx); batch.Len() > 1024 { 118 loadBatch(batch) 119 batch = batch[:0] 120 } 121 } 122 log.Info("Loaded local transaction journal", "transactions", total, "dropped", dropped) 123 124 return failure 125 } 126 127 //insert将指定的事务添加到本地磁盘日志。 128 func (journal *txJournal) insert(tx *types.Transaction) error { 129 if journal.writer == nil { 130 return errNoActiveJournal 131 } 132 if err := rlp.Encode(journal.writer, tx); err != nil { 133 return err 134 } 135 return nil 136 } 137 138 //Rotate根据当前的内容重新生成事务日记帐 139 //事务池。 140 func (journal *txJournal) rotate(all map[common.Address]types.Transactions) error { 141 //关闭当前日记帐(如果有打开的日记帐) 142 if journal.writer != nil { 143 if err := journal.writer.Close(); err != nil { 144 return err 145 } 146 journal.writer = nil 147 } 148 //生成包含当前池内容的新日记 149 replacement, err := os.OpenFile(journal.path+".new", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755) 150 if err != nil { 151 return err 152 } 153 journaled := 0 154 for _, txs := range all { 155 for _, tx := range txs { 156 if err = rlp.Encode(replacement, tx); err != nil { 157 replacement.Close() 158 return err 159 } 160 } 161 journaled += len(txs) 162 } 163 replacement.Close() 164 165 //用新生成的日志替换活日志 166 if err = os.Rename(journal.path+".new", journal.path); err != nil { 167 return err 168 } 169 sink, err := os.OpenFile(journal.path, os.O_WRONLY|os.O_APPEND, 0755) 170 if err != nil { 171 return err 172 } 173 journal.writer = sink 174 log.Info("Regenerated local transaction journal", "transactions", journaled, "accounts", len(all)) 175 176 return nil 177 } 178 179 //close将事务日志内容刷新到磁盘并关闭文件。 180 func (journal *txJournal) close() error { 181 var err error 182 183 if journal.writer != nil { 184 err = journal.writer.Close() 185 journal.writer = nil 186 } 187 return err 188 }