github.com/BlockABC/godash@v0.0.0-20191112120524-f4aa3a32c566/btcd.go (about) 1 // Copyright (c) 2013-2016 The btcsuite developers 2 // Copyright (c) 2016 The Dash developers 3 // Use of this source code is governed by an ISC 4 // license that can be found in the LICENSE file. 5 6 package main 7 8 import ( 9 "fmt" 10 "net" 11 "net/http" 12 _ "net/http/pprof" 13 "os" 14 "runtime" 15 "runtime/debug" 16 "runtime/pprof" 17 18 "github.com/BlockABC/godash/blockchain/indexers" 19 "github.com/BlockABC/godash/limits" 20 ) 21 22 var ( 23 cfg *config 24 shutdownChannel = make(chan struct{}) 25 ) 26 27 // winServiceMain is only invoked on Windows. It detects when btcd is running 28 // as a service and reacts accordingly. 29 var winServiceMain func() (bool, error) 30 31 // btcdMain is the real main function for btcd. It is necessary to work around 32 // the fact that deferred functions do not run when os.Exit() is called. The 33 // optional serverChan parameter is mainly used by the service code to be 34 // notified with the server once it is setup so it can gracefully stop it when 35 // requested from the service control manager. 36 func btcdMain(serverChan chan<- *server) error { 37 // Load configuration and parse command line. This function also 38 // initializes logging and configures it accordingly. 39 tcfg, _, err := loadConfig() 40 if err != nil { 41 return err 42 } 43 cfg = tcfg 44 defer backendLog.Flush() 45 46 // Show version at startup. 47 btcdLog.Infof("Version %s", version()) 48 49 // Enable http profiling server if requested. 50 if cfg.Profile != "" { 51 go func() { 52 listenAddr := net.JoinHostPort("", cfg.Profile) 53 btcdLog.Infof("Profile server listening on %s", listenAddr) 54 profileRedirect := http.RedirectHandler("/debug/pprof", 55 http.StatusSeeOther) 56 http.Handle("/", profileRedirect) 57 btcdLog.Errorf("%v", http.ListenAndServe(listenAddr, nil)) 58 }() 59 } 60 61 // Write cpu profile if requested. 62 if cfg.CPUProfile != "" { 63 f, err := os.Create(cfg.CPUProfile) 64 if err != nil { 65 btcdLog.Errorf("Unable to create cpu profile: %v", err) 66 return err 67 } 68 pprof.StartCPUProfile(f) 69 defer f.Close() 70 defer pprof.StopCPUProfile() 71 } 72 73 // Perform upgrades to btcd as new versions require it. 74 if err := doUpgrades(); err != nil { 75 btcdLog.Errorf("%v", err) 76 return err 77 } 78 79 // Load the block database. 80 db, err := loadBlockDB() 81 if err != nil { 82 btcdLog.Errorf("%v", err) 83 return err 84 } 85 defer db.Close() 86 87 // Ensure the database is sync'd and closed on Ctrl+C. 88 addInterruptHandler(func() { 89 btcdLog.Infof("Gracefully shutting down the database...") 90 db.Close() 91 }) 92 93 // Drop indexes and exit if requested. 94 // 95 // NOTE: The order is important here because dropping the tx index also 96 // drops the address index since it relies on it. 97 if cfg.DropAddrIndex { 98 if err := indexers.DropAddrIndex(db); err != nil { 99 btcdLog.Errorf("%v", err) 100 return err 101 } 102 103 return nil 104 } 105 if cfg.DropTxIndex { 106 if err := indexers.DropTxIndex(db); err != nil { 107 btcdLog.Errorf("%v", err) 108 return err 109 } 110 111 return nil 112 } 113 114 // Create server and start it. 115 server, err := newServer(cfg.Listeners, db, activeNetParams.Params) 116 if err != nil { 117 // TODO(oga) this logging could do with some beautifying. 118 btcdLog.Errorf("Unable to start server on %v: %v", 119 cfg.Listeners, err) 120 return err 121 } 122 addInterruptHandler(func() { 123 btcdLog.Infof("Gracefully shutting down the server...") 124 server.Stop() 125 server.WaitForShutdown() 126 }) 127 server.Start() 128 if serverChan != nil { 129 serverChan <- server 130 } 131 132 // Monitor for graceful server shutdown and signal the main goroutine 133 // when done. This is done in a separate goroutine rather than waiting 134 // directly so the main goroutine can be signaled for shutdown by either 135 // a graceful shutdown or from the main interrupt handler. This is 136 // necessary since the main goroutine must be kept running long enough 137 // for the interrupt handler goroutine to finish. 138 go func() { 139 server.WaitForShutdown() 140 srvrLog.Infof("Server shutdown complete") 141 shutdownChannel <- struct{}{} 142 }() 143 144 // Wait for shutdown signal from either a graceful server stop or from 145 // the interrupt handler. 146 <-shutdownChannel 147 btcdLog.Info("Shutdown complete") 148 return nil 149 } 150 151 func main() { 152 // Use all processor cores. 153 runtime.GOMAXPROCS(runtime.NumCPU()) 154 155 // Block and transaction processing can cause bursty allocations. This 156 // limits the garbage collector from excessively overallocating during 157 // bursts. This value was arrived at with the help of profiling live 158 // usage. 159 debug.SetGCPercent(10) 160 161 // Up some limits. 162 if err := limits.SetLimits(); err != nil { 163 fmt.Fprintf(os.Stderr, "failed to set limits: %v\n", err) 164 os.Exit(1) 165 } 166 167 // Call serviceMain on Windows to handle running as a service. When 168 // the return isService flag is true, exit now since we ran as a 169 // service. Otherwise, just fall through to normal operation. 170 if runtime.GOOS == "windows" { 171 isService, err := winServiceMain() 172 if err != nil { 173 fmt.Println(err) 174 os.Exit(1) 175 } 176 if isService { 177 os.Exit(0) 178 } 179 } 180 181 // Work around defer not working after os.Exit() 182 if err := btcdMain(nil); err != nil { 183 os.Exit(1) 184 } 185 }