github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/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  	"fmt"
    22  	"io"
    23  	"os"
    24  	"os/signal"
    25  	"runtime"
    26  	"syscall"
    27  	"time"
    28  
    29  	"gopkg.in/urfave/cli.v1"
    30  	
    31  	"github.com/unicornultrafoundation/go-u2u/common"
    32  	"github.com/unicornultrafoundation/go-u2u/eth/ethconfig"
    33  	"github.com/unicornultrafoundation/go-u2u/internal/debug"
    34  	"github.com/unicornultrafoundation/go-u2u/log"
    35  	"github.com/unicornultrafoundation/go-u2u/node"
    36  )
    37  
    38  const (
    39  	importBatchSize = 2500
    40  )
    41  
    42  // Fatalf formats a message to standard error and exits the program.
    43  // The message is also printed to standard output if standard error
    44  // is redirected to a different file.
    45  func Fatalf(format string, args ...interface{}) {
    46  	w := io.MultiWriter(os.Stdout, os.Stderr)
    47  	if runtime.GOOS == "windows" {
    48  		// The SameFile check below doesn't work on Windows.
    49  		// stdout is unlikely to get redirected though, so just print there.
    50  		w = os.Stdout
    51  	} else {
    52  		outf, _ := os.Stdout.Stat()
    53  		errf, _ := os.Stderr.Stat()
    54  		if outf != nil && errf != nil && os.SameFile(outf, errf) {
    55  			w = os.Stderr
    56  		}
    57  	}
    58  	fmt.Fprintf(w, "Fatal: "+format+"\n", args...)
    59  	os.Exit(1)
    60  }
    61  
    62  func StartNode(ctx *cli.Context, stack *node.Node) {
    63  	if err := stack.Start(); err != nil {
    64  		Fatalf("Error starting protocol stack: %v", err)
    65  	}
    66  	go func() {
    67  		sigc := make(chan os.Signal, 1)
    68  		signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM)
    69  		defer signal.Stop(sigc)
    70  
    71  		minFreeDiskSpace := ethconfig.Defaults.TrieDirtyCache
    72  		if ctx.GlobalIsSet(MinFreeDiskSpaceFlag.Name) {
    73  			minFreeDiskSpace = ctx.GlobalInt(MinFreeDiskSpaceFlag.Name)
    74  		} else {
    75  			minFreeDiskSpace = 8192
    76  		}
    77  		if minFreeDiskSpace > 0 {
    78  			go monitorFreeDiskSpace(sigc, stack.InstanceDir(), uint64(minFreeDiskSpace)*1024*1024)
    79  		}
    80  
    81  		<-sigc
    82  		log.Info("Got interrupt, shutting down...")
    83  		go stack.Close()
    84  		for i := 10; i > 0; i-- {
    85  			<-sigc
    86  			if i > 1 {
    87  				log.Warn("Already shutting down, interrupt more to panic.", "times", i-1)
    88  			}
    89  		}
    90  		debug.Exit() // ensure trace and CPU profile data is flushed.
    91  		debug.LoudPanic("boom")
    92  	}()
    93  }
    94  
    95  func monitorFreeDiskSpace(sigc chan os.Signal, path string, freeDiskSpaceCritical uint64) {
    96  	for {
    97  		freeSpace, err := GetFreeDiskSpace(path)
    98  		if err != nil {
    99  			log.Warn("Failed to get free disk space", "path", path, "err", err)
   100  			break
   101  		}
   102  		if freeSpace < freeDiskSpaceCritical {
   103  			log.Error("Low disk space. Gracefully shutting down client to prevent database corruption.", "available", common.StorageSize(freeSpace))
   104  			sigc <- syscall.SIGTERM
   105  			break
   106  		} else if freeSpace < 2*freeDiskSpaceCritical {
   107  			log.Warn("Disk space is running low. client will shutdown if disk space runs below critical level.", "available", common.StorageSize(freeSpace), "critical_level", common.StorageSize(freeDiskSpaceCritical))
   108  		}
   109  		time.Sleep(60 * time.Second)
   110  	}
   111  }