state.go raw

   1  // +build !headless
   2  
   3  package state
   4  
   5  import (
   6  	"fmt"
   7  	"runtime"
   8  	"strings"
   9  	"sync"
  10  
  11  	"go.uber.org/atomic"
  12  
  13  	"github.com/p9c/p9/pkg/chaincfg"
  14  	"github.com/p9c/p9/pkg/chainclient"
  15  	"github.com/p9c/p9/pkg/chainrpc"
  16  	"github.com/p9c/p9/pkg/ctrl"
  17  	"github.com/p9c/p9/pkg/opts/opt"
  18  	"github.com/p9c/p9/pod/config"
  19  
  20  	"github.com/p9c/p9/pkg/qu"
  21  
  22  	"github.com/p9c/p9/cmd/node/active"
  23  	"github.com/p9c/p9/pkg/util/lang"
  24  )
  25  
  26  // type _dtype int
  27  //
  28  // var _d _dtype
  29  
  30  // State stores all the common state data used in pod
  31  type State struct {
  32  	sync.Mutex
  33  	WaitGroup sync.WaitGroup
  34  	KillAll   qu.C
  35  	// Config is the pod all-in-one server config
  36  	Config *config.Config
  37  	// ConfigMap
  38  	ConfigMap map[string]opt.Option
  39  	// StateCfg is a reference to the main node state configuration struct
  40  	StateCfg *active.Config
  41  	// ActiveNet is the active net parameters
  42  	ActiveNet *chaincfg.Params
  43  	// Language libraries
  44  	Language *lang.Lexicon
  45  	// Node is the run state of the node
  46  	Node atomic.Bool
  47  	// NodeReady is closed when it is ready then always returns
  48  	NodeReady qu.C
  49  	// NodeKill is the killswitch for the Node
  50  	NodeKill qu.C
  51  	// Wallet is the run state of the wallet
  52  	Wallet atomic.Bool
  53  	// WalletKill is the killswitch for the Wallet
  54  	WalletKill qu.C
  55  	// RPCServer is needed to directly query data
  56  	RPCServer *chainrpc.Server
  57  	// NodeChan relays the chain RPC server to the main
  58  	NodeChan chan *chainrpc.Server
  59  	// // WalletServer is needed to query the wallet
  60  	// WalletServer *wallet.Wallet
  61  	// ChainClientReady signals when the chain client is ready
  62  	ChainClientReady qu.C
  63  	// ChainClient is the wallet's chain RPC client
  64  	ChainClient *chainclient.RPCClient
  65  	// RealNode is the main node
  66  	RealNode *chainrpc.Node
  67  	// Hashrate is the current total hashrate from kopach workers taking work from this node
  68  	Hashrate atomic.Uint64
  69  	// Controller is the state of the controller
  70  	Controller *ctrl.State
  71  	// OtherNodesCounter is the count of nodes connected automatically on the LAN
  72  	OtherNodesCounter atomic.Int32
  73  	waitChangers []string
  74  	waitCounter  int
  75  	Syncing           *atomic.Bool
  76  	IsGUI             bool
  77  }
  78  
  79  func (cx *State) WaitAdd() {
  80  	cx.WaitGroup.Add(1)
  81  	_, file, line, _ := runtime.Caller(1)
  82  	record := fmt.Sprintf("+ %s:%d", file, line)
  83  	cx.waitChangers = append(cx.waitChangers, record)
  84  	cx.waitCounter++
  85  	D.Ln("added to waitgroup", record, cx.waitCounter)
  86  	D.Ln(cx.PrintWaitChangers())
  87  }
  88  
  89  func (cx *State) WaitDone() {
  90  	_, file, line, _ := runtime.Caller(1)
  91  	record := fmt.Sprintf("- %s:%d", file, line)
  92  	cx.waitChangers = append(cx.waitChangers, record)
  93  	cx.waitCounter--
  94  	D.Ln("removed from waitgroup", record, cx.waitCounter)
  95  	D.Ln(cx.PrintWaitChangers())
  96  	qu.PrintChanState()
  97  	cx.WaitGroup.Done()
  98  }
  99  
 100  func (cx *State) WaitWait() {
 101  	D.Ln(cx.PrintWaitChangers())
 102  	cx.WaitGroup.Wait()
 103  }
 104  
 105  func (cx *State) PrintWaitChangers() string {
 106  	o := "Calls that change context waitgroup values:\n"
 107  	for i := range cx.waitChangers {
 108  		o += strings.Repeat(" ", 48)
 109  		o += cx.waitChangers[i] + "\n"
 110  	}
 111  	o += strings.Repeat(" ", 48)
 112  	o += "current total:"
 113  	o += fmt.Sprint(cx.waitCounter)
 114  	return o
 115  }
 116  
 117  func GetContext(cx *State) *chainrpc.Context {
 118  	return &chainrpc.Context{
 119  		Config: cx.Config, StateCfg: cx.StateCfg, ActiveNet: cx.ActiveNet,
 120  		Hashrate: cx.Hashrate,
 121  	}
 122  }
 123  
 124  // func (cx *State) IsCurrent() (is bool) {
 125  // 	rn := cx.RealNode
 126  // 	cc := rn.ConnectedCount()
 127  // 	othernodes := cx.OtherNodesCounter.Load()
 128  // 	if !cx.Config.LAN.True() {
 129  // 		cc -= othernodes
 130  // 	}
 131  // 	D.Ln(cc, "nodes connected")
 132  // 	connected := cc > 0
 133  // 	is = rn.Chain.IsCurrent() &&
 134  // 		rn.SyncManager.IsCurrent() &&
 135  // 		connected &&
 136  // 		rn.Chain.BestChain.Height() >= rn.HighestKnown.Load() || cx.Config.Solo.True()
 137  // 	D.Ln(
 138  // 		"is current:", is, "-", rn.Chain.IsCurrent(), rn.SyncManager.IsCurrent(),
 139  // 		*cx.Config.Solo, "connected", rn.HighestKnown.Load(), rn.Chain.BestChain.Height(),
 140  // 		othernodes,
 141  // 	)
 142  // 	return is
 143  // }
 144