github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/cmd/utils/cmd.go (about)

     1  // Copyright 2014 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU 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  // go-ethereum 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 General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package utils contains internal helper functions for go-ethereum commands.
    18  package utils
    19  
    20  import (
    21  	"compress/gzip"
    22  	"fmt"
    23  	"io"
    24  	"os"
    25  	"os/signal"
    26  	"regexp"
    27  	"runtime"
    28  	"strings"
    29  
    30  	"github.com/atheioschain/go-atheios/common"
    31  	"github.com/atheioschain/go-atheios/core"
    32  	"github.com/atheioschain/go-atheios/core/types"
    33  	"github.com/atheioschain/go-atheios/internal/debug"
    34  	"github.com/atheioschain/go-atheios/logger"
    35  	"github.com/atheioschain/go-atheios/logger/glog"
    36  	"github.com/atheioschain/go-atheios/node"
    37  	"github.com/atheioschain/go-atheios/rlp"
    38  )
    39  
    40  const (
    41  	importBatchSize = 2500
    42  )
    43  
    44  func openLogFile(Datadir string, filename string) *os.File {
    45  	path := common.AbsolutePath(Datadir, filename)
    46  	file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    47  	if err != nil {
    48  		panic(fmt.Sprintf("error opening log file '%s': %v", filename, err))
    49  	}
    50  	return file
    51  }
    52  
    53  // Fatalf formats a message to standard error and exits the program.
    54  // The message is also printed to standard output if standard error
    55  // is redirected to a different file.
    56  func Fatalf(format string, args ...interface{}) {
    57  	w := io.MultiWriter(os.Stdout, os.Stderr)
    58  	if runtime.GOOS == "windows" {
    59  		// The SameFile check below doesn't work on Windows.
    60  		// stdout is unlikely to get redirected though, so just print there.
    61  		w = os.Stdout
    62  	} else {
    63  		outf, _ := os.Stdout.Stat()
    64  		errf, _ := os.Stderr.Stat()
    65  		if outf != nil && errf != nil && os.SameFile(outf, errf) {
    66  			w = os.Stderr
    67  		}
    68  	}
    69  	fmt.Fprintf(w, "Fatal: "+format+"\n", args...)
    70  	os.Exit(1)
    71  }
    72  
    73  func StartNode(stack *node.Node) {
    74  	if err := stack.Start(); err != nil {
    75  		Fatalf("Error starting protocol stack: %v", err)
    76  	}
    77  	go func() {
    78  		sigc := make(chan os.Signal, 1)
    79  		signal.Notify(sigc, os.Interrupt)
    80  		defer signal.Stop(sigc)
    81  		<-sigc
    82  		glog.V(logger.Info).Infoln("Got interrupt, shutting down...")
    83  		go stack.Stop()
    84  		for i := 10; i > 0; i-- {
    85  			<-sigc
    86  			if i > 1 {
    87  				glog.V(logger.Info).Infof("Already shutting down, interrupt %d more times for panic.", i-1)
    88  			}
    89  		}
    90  		debug.Exit() // ensure trace and CPU profile data is flushed.
    91  		debug.LoudPanic("boom")
    92  	}()
    93  }
    94  
    95  func FormatTransactionData(data string) []byte {
    96  	d := common.StringToByteFunc(data, func(s string) (ret []byte) {
    97  		slice := regexp.MustCompile(`\n|\s`).Split(s, 1000000000)
    98  		for _, dataItem := range slice {
    99  			d := common.FormatData(dataItem)
   100  			ret = append(ret, d...)
   101  		}
   102  		return
   103  	})
   104  
   105  	return d
   106  }
   107  
   108  func ImportChain(chain *core.BlockChain, fn string) error {
   109  	// Watch for Ctrl-C while the import is running.
   110  	// If a signal is received, the import will stop at the next batch.
   111  	interrupt := make(chan os.Signal, 1)
   112  	stop := make(chan struct{})
   113  	signal.Notify(interrupt, os.Interrupt)
   114  	defer signal.Stop(interrupt)
   115  	defer close(interrupt)
   116  	go func() {
   117  		if _, ok := <-interrupt; ok {
   118  			glog.Info("caught interrupt during import, will stop at next batch")
   119  		}
   120  		close(stop)
   121  	}()
   122  	checkInterrupt := func() bool {
   123  		select {
   124  		case <-stop:
   125  			return true
   126  		default:
   127  			return false
   128  		}
   129  	}
   130  
   131  	glog.Infoln("Importing blockchain ", fn)
   132  	fh, err := os.Open(fn)
   133  	if err != nil {
   134  		return err
   135  	}
   136  	defer fh.Close()
   137  
   138  	var reader io.Reader = fh
   139  	if strings.HasSuffix(fn, ".gz") {
   140  		if reader, err = gzip.NewReader(reader); err != nil {
   141  			return err
   142  		}
   143  	}
   144  
   145  	stream := rlp.NewStream(reader, 0)
   146  
   147  	// Run actual the import.
   148  	blocks := make(types.Blocks, importBatchSize)
   149  	n := 0
   150  	for batch := 0; ; batch++ {
   151  		// Load a batch of RLP blocks.
   152  		if checkInterrupt() {
   153  			return fmt.Errorf("interrupted")
   154  		}
   155  		i := 0
   156  		for ; i < importBatchSize; i++ {
   157  			var b types.Block
   158  			if err := stream.Decode(&b); err == io.EOF {
   159  				break
   160  			} else if err != nil {
   161  				return fmt.Errorf("at block %d: %v", n, err)
   162  			}
   163  			// don't import first block
   164  			if b.NumberU64() == 0 {
   165  				i--
   166  				continue
   167  			}
   168  			blocks[i] = &b
   169  			n++
   170  		}
   171  		if i == 0 {
   172  			break
   173  		}
   174  		// Import the batch.
   175  		if checkInterrupt() {
   176  			return fmt.Errorf("interrupted")
   177  		}
   178  		if hasAllBlocks(chain, blocks[:i]) {
   179  			glog.Infof("skipping batch %d, all blocks present [%x / %x]",
   180  				batch, blocks[0].Hash().Bytes()[:4], blocks[i-1].Hash().Bytes()[:4])
   181  			continue
   182  		}
   183  
   184  		if _, err := chain.InsertChain(blocks[:i]); err != nil {
   185  			return fmt.Errorf("invalid block %d: %v", n, err)
   186  		}
   187  	}
   188  	return nil
   189  }
   190  
   191  func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool {
   192  	for _, b := range bs {
   193  		if !chain.HasBlock(b.Hash()) {
   194  			return false
   195  		}
   196  	}
   197  	return true
   198  }
   199  
   200  func ExportChain(blockchain *core.BlockChain, fn string) error {
   201  	glog.Infoln("Exporting blockchain to ", fn)
   202  	fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
   203  	if err != nil {
   204  		return err
   205  	}
   206  	defer fh.Close()
   207  
   208  	var writer io.Writer = fh
   209  	if strings.HasSuffix(fn, ".gz") {
   210  		writer = gzip.NewWriter(writer)
   211  		defer writer.(*gzip.Writer).Close()
   212  	}
   213  
   214  	if err := blockchain.Export(writer); err != nil {
   215  		return err
   216  	}
   217  	glog.Infoln("Exported blockchain to ", fn)
   218  
   219  	return nil
   220  }
   221  
   222  func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, last uint64) error {
   223  	glog.Infoln("Exporting blockchain to ", fn)
   224  	// TODO verify mode perms
   225  	fh, err := os.OpenFile(fn, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm)
   226  	if err != nil {
   227  		return err
   228  	}
   229  	defer fh.Close()
   230  
   231  	var writer io.Writer = fh
   232  	if strings.HasSuffix(fn, ".gz") {
   233  		writer = gzip.NewWriter(writer)
   234  		defer writer.(*gzip.Writer).Close()
   235  	}
   236  
   237  	if err := blockchain.ExportN(writer, first, last); err != nil {
   238  		return err
   239  	}
   240  	glog.Infoln("Exported blockchain to ", fn)
   241  	return nil
   242  }