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  }