github.com/amazechain/amc@v0.1.3/internal/download/process.go (about) 1 // Copyright 2022 The AmazeChain Authors 2 // This file is part of the AmazeChain library. 3 // 4 // The AmazeChain library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The AmazeChain library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the AmazeChain library. If not, see <http://www.gnu.org/licenses/>. 16 17 package download 18 19 import ( 20 "github.com/amazechain/amc/utils" 21 "github.com/holiman/uint256" 22 "math/rand" 23 "time" 24 25 block2 "github.com/amazechain/amc/common/block" 26 "github.com/amazechain/amc/log" 27 ) 28 29 func (d *Downloader) processHeaders() error { 30 31 defer log.Info("Headers process Finished") 32 var ( 33 headerNumberPool []uint256.Int 34 startProcess = false 35 ) 36 37 tick := time.NewTicker(time.Duration(1 * time.Second)) 38 defer tick.Stop() 39 40 for { 41 if startProcess && len(d.headerTasks) == 0 && len(d.headerProcessingTasks) == 0 { 42 if len(headerNumberPool) > 0 { 43 d.bodyTaskPoolLock.Lock() 44 d.bodyTaskPool = append(d.bodyTaskPool, &blockTask{ 45 taskID: rand.Uint64(), 46 number: headerNumberPool[:], 47 }) 48 d.bodyTaskPoolLock.Unlock() 49 } 50 break 51 } 52 53 select { 54 case <-d.ctx.Done(): 55 return ErrCanceled 56 case task := <-d.headerProcCh: 57 58 d.once.Do(func() { 59 startProcess = true 60 log.Info("Starting body downloads") 61 }) 62 63 d.headerTaskLock.Lock() 64 if _, ok := d.headerProcessingTasks[task.taskID]; ok { 65 delete(d.headerProcessingTasks, task.taskID) 66 } 67 log.Tracef("received headers from remote peers , the header counts is %v", len(task.headers)) 68 for _, header := range task.headers { 69 headerNumberPool = append(headerNumberPool, *utils.ConvertH256ToUint256Int(header.Number)) 70 if len(headerNumberPool) >= maxBodiesFetch { 71 d.bodyTaskPoolLock.Lock() 72 // 73 number := make([]uint256.Int, len(headerNumberPool)) 74 copy(number, headerNumberPool) 75 //d.log.Infof("copy count %d", c) 76 headerNumberPool = headerNumberPool[0:0] 77 // 78 d.bodyTaskPool = append(d.bodyTaskPool, &blockTask{ 79 taskID: rand.Uint64(), 80 number: number, 81 }) 82 d.bodyTaskPoolLock.Unlock() 83 } 84 d.headerResultStore[*utils.ConvertH256ToUint256Int(header.Number)] = header 85 //d.log.Infof("process header %v", header) 86 } 87 d.headerTaskLock.Unlock() 88 case <-tick.C: 89 tick.Reset(time.Duration(3 * time.Second)) 90 continue 91 } 92 } 93 return nil 94 } 95 96 // processBodies 97 func (d *Downloader) processBodies() error { 98 tick := time.NewTicker(time.Duration(1 * time.Second)) 99 defer tick.Stop() 100 defer log.Info("Process bodies finished") 101 startProcess := false 102 103 for { 104 if startProcess && len(d.bodyTaskPool) == 0 && len(d.bodyProcessingTasks) == 0 { 105 break 106 } 107 108 select { 109 case <-d.ctx.Done(): 110 return ErrCanceled 111 case response := <-d.blockProcCh: 112 113 d.once.Do(func() { 114 startProcess = true 115 log.Info("Starting process bodies") 116 }) 117 118 //d.log.Infof("processing body task id is %v, response is: %v", response.taskID, response) 119 120 d.bodyTaskPoolLock.Lock() 121 if _, ok := d.bodyProcessingTasks[response.taskID]; ok { 122 delete(d.bodyProcessingTasks, response.taskID) 123 } 124 125 log.Debugf("received block from remote peers , the block counts is %v", len(response.bodies)) 126 for _, body := range response.bodies { 127 d.bodyResultStore[*utils.ConvertH256ToUint256Int(body.Header.Number)] = body 128 } 129 d.bodyTaskPoolLock.Unlock() 130 case <-tick.C: 131 tick.Reset(time.Duration(3 * time.Second)) 132 continue 133 } 134 } 135 return nil 136 } 137 138 func (d *Downloader) processChain() error { 139 tick := time.NewTicker(time.Duration(1 * time.Second)) 140 defer tick.Stop() 141 startProcess := false 142 defer log.Info("Process chain Finished") 143 144 for { 145 if startProcess && len(d.bodyResultStore) == 0 && len(d.bodyTaskPool) == 0 && len(d.bodyProcessingTasks) == 0 && len(d.headerTasks) == 0 && len(d.headerProcessingTasks) == 0 { 146 break 147 } 148 // 149 d.once.Do(func() { 150 startProcess = true 151 log.Info("Starting process chain") 152 }) 153 154 select { 155 case <-d.ctx.Done(): 156 return ErrCanceled 157 case <-tick.C: 158 159 d.bodyTaskPoolLock.Lock() 160 wantBlockNumber := new(uint256.Int).AddUint64(d.bc.CurrentBlock().Number64(), 1) 161 log.Tracef("want block %d have blocks count is %d", wantBlockNumber.Uint64(), len(d.bodyResultStore)) 162 163 blocks := make([]block2.IBlock, 0) 164 for i := 0; i < maxResultsProcess; i++ { 165 if blockMsg, ok := d.bodyResultStore[*wantBlockNumber]; ok { 166 var block block2.Block 167 err := block.FromProtoMessage(blockMsg) 168 if err != nil { 169 //todo 170 break 171 } 172 delete(d.bodyResultStore, *wantBlockNumber) 173 blocks = append(blocks, &block) 174 } 175 wantBlockNumber.AddUint64(wantBlockNumber, 1) 176 } 177 178 if len(blocks) == 0 { 179 d.bodyTaskPoolLock.Unlock() 180 continue 181 } 182 183 first, last := blocks[0].Header(), blocks[len(blocks)-1].Header() 184 log.Info("Inserting downloaded chain", "items", len(blocks), 185 "firstnum", first.Number64().Uint64(), "firsthash", first.Hash(), 186 "lastnum", last.Number64().Uint64(), "lasthash", last.Hash(), 187 ) 188 189 if index, err := d.bc.InsertChain(blocks); err != nil { 190 //inserted = false 191 if index < len(blocks) { 192 log.Errorf("downloader failed to inster new block in blockchain, err:%v", err) 193 } else { 194 } 195 d.bodyTaskPoolLock.Unlock() 196 return err 197 198 } else { 199 //inserted = true 200 201 } 202 d.bodyTaskPoolLock.Unlock() 203 } 204 } 205 return nil 206 }