btcd/btcd.go

167 lines
4.4 KiB
Go
Raw Normal View History

// Copyright (c) 2013-2014 The btcsuite developers
2013-08-06 23:55:22 +02:00
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package main
import (
"fmt"
2013-08-06 23:55:22 +02:00
"net"
"net/http"
_ "net/http/pprof"
2013-08-06 23:55:22 +02:00
"os"
"runtime"
"runtime/pprof"
2014-07-02 15:50:08 +02:00
"github.com/btcsuite/btcd/limits"
2013-08-06 23:55:22 +02:00
)
var (
cfg *config
shutdownChannel = make(chan struct{})
2013-08-06 23:55:22 +02:00
)
2014-01-11 05:32:05 +01:00
// winServiceMain is only invoked on Windows. It detects when btcd is running
// as a service and reacts accordingly.
var winServiceMain func() (bool, error)
2013-08-06 23:55:22 +02:00
// btcdMain is the real main function for btcd. It is necessary to work around
// the fact that deferred functions do not run when os.Exit() is called. The
// optional serverChan parameter is mainly used by the service code to be
// notified with the server once it is setup so it can gracefully stop it when
// requested from the service control manager.
func btcdMain(serverChan chan<- *server) error {
// Load configuration and parse command line. This function also
// initializes logging and configures it accordingly.
2013-08-06 23:55:22 +02:00
tcfg, _, err := loadConfig()
if err != nil {
return err
}
cfg = tcfg
defer backendLog.Flush()
2013-08-06 23:55:22 +02:00
2013-10-15 22:54:00 +02:00
// Show version at startup.
btcdLog.Infof("Version %s", version())
2013-10-15 22:54:00 +02:00
// Enable http profiling server if requested.
if cfg.Profile != "" {
go func() {
listenAddr := net.JoinHostPort("", cfg.Profile)
btcdLog.Infof("Profile server listening on %s", listenAddr)
profileRedirect := http.RedirectHandler("/debug/pprof",
http.StatusSeeOther)
http.Handle("/", profileRedirect)
btcdLog.Errorf("%v", http.ListenAndServe(listenAddr, nil))
}()
}
// Write cpu profile if requested.
golint -min_confidence=0.3 . This commits removes a number of golint warnings. There is a class of warnings which I can't fix due to unsufficient knowledge of the domain at this point. These are listed here: addrmanager.go:907:1: comment on exported method AddrManager.Attempt should be of the form "Attempt ..." addrmanager.go:1048:1: exported function RFC1918 should have comment or be unexported addrmanager.go:1058:1: exported function RFC3849 should have comment or be unexported addrmanager.go:1065:1: exported function RFC3927 should have comment or be unexported addrmanager.go:1073:1: exported function RFC3964 should have comment or be unexported addrmanager.go:1081:1: exported function RFC4193 should have comment or be unexported addrmanager.go:1089:1: exported function RFC4380 should have comment or be unexported addrmanager.go:1097:1: exported function RFC4843 should have comment or be unexported addrmanager.go:1105:1: exported function RFC4862 should have comment or be unexported addrmanager.go:1113:1: exported function RFC6052 should have comment or be unexported addrmanager.go:1121:1: exported function RFC6145 should have comment or be unexported addrmanager.go:1128:1: exported function Tor should have comment or be unexported addrmanager.go:1143:1: exported function Local should have comment or be unexported addrmanager.go:1228:2: exported const InterfacePrio should have comment (or a comment on this block) or be unexported discovery.go:26:2: exported var ErrTorInvalidAddressResponse should have comment or be unexported limits/limits_unix.go:19:1: exported function SetLimits should have comment or be unexported limits/limits_windows.go:7:1: exported function SetLimits should have comment or be unexported util/dropafter/dropafter.go:22:6: exported type ShaHash should have comment or be unexported util/dropafter/dropafter.go:38:2: exported const ArgSha should have comment (or a comment on this block) or be unexported util/dropafter/dropafter.go:128:5: exported var ErrBadShaPrefix should have comment or be unexported util/dropafter/dropafter.go:129:5: exported var ErrBadShaLen should have comment or be unexported util/dropafter/dropafter.go:130:5: exported var ErrBadShaChar should have comment or be unexported util/showblock/showblock.go:24:6: exported type ShaHash should have comment or be unexported util/showblock/showblock.go:46:2: exported const ArgSha should have comment (or a comment on this block) or be unexported util/showblock/showblock.go:163:1: exported function DumpBlock should have comment or be unexported util/showblock/showblock.go:211:5: exported var ErrBadShaPrefix should have comment or be unexported util/showblock/showblock.go:212:5: exported var ErrBadShaLen should have comment or be unexported util/showblock/showblock.go:213:5: exported var ErrBadShaChar should have comment or be unexported
2014-07-02 16:25:42 +02:00
if cfg.CPUProfile != "" {
f, err := os.Create(cfg.CPUProfile)
if err != nil {
btcdLog.Errorf("Unable to create cpu profile: %v", err)
return err
}
pprof.StartCPUProfile(f)
defer f.Close()
defer pprof.StopCPUProfile()
}
// Perform upgrades to btcd as new versions require it.
2013-10-08 02:24:44 +02:00
if err := doUpgrades(); err != nil {
btcdLog.Errorf("%v", err)
return err
}
2013-08-06 23:55:22 +02:00
// Load the block database.
db, err := loadBlockDB()
if err != nil {
btcdLog.Errorf("%v", err)
2013-08-06 23:55:22 +02:00
return err
}
defer db.Close()
if cfg.DropAddrIndex {
btcdLog.Info("Deleting entire addrindex.")
err := db.DeleteAddrIndex()
if err != nil {
btcdLog.Errorf("Unable to delete the addrindex: %v", err)
return err
}
btcdLog.Info("Successfully deleted addrindex, exiting")
return nil
}
2013-08-06 23:55:22 +02:00
// Ensure the database is sync'd and closed on Ctrl+C.
addInterruptHandler(func() {
btcdLog.Infof("Gracefully shutting down the database...")
2013-08-06 23:55:22 +02:00
db.RollbackClose()
})
// Create server and start it.
server, err := newServer(cfg.Listeners, db, activeNetParams.Params)
2013-08-06 23:55:22 +02:00
if err != nil {
// TODO(oga) this logging could do with some beautifying.
btcdLog.Errorf("Unable to start server on %v: %v",
cfg.Listeners, err)
2013-08-06 23:55:22 +02:00
return err
}
addInterruptHandler(func() {
btcdLog.Infof("Gracefully shutting down the server...")
server.Stop()
server.WaitForShutdown()
})
2013-08-06 23:55:22 +02:00
server.Start()
if serverChan != nil {
serverChan <- server
}
2013-08-06 23:55:22 +02:00
// Monitor for graceful server shutdown and signal the main goroutine
// when done. This is done in a separate goroutine rather than waiting
// directly so the main goroutine can be signaled for shutdown by either
// a graceful shutdown or from the main interrupt handler. This is
// necessary since the main goroutine must be kept running long enough
// for the interrupt handler goroutine to finish.
go func() {
server.WaitForShutdown()
srvrLog.Infof("Server shutdown complete")
shutdownChannel <- struct{}{}
}()
// Wait for shutdown signal from either a graceful server stop or from
// the interrupt handler.
<-shutdownChannel
btcdLog.Info("Shutdown complete")
2013-08-06 23:55:22 +02:00
return nil
}
func main() {
// Use all processor cores.
runtime.GOMAXPROCS(runtime.NumCPU())
// Up some limits.
if err := limits.SetLimits(); err != nil {
fmt.Fprintf(os.Stderr, "failed to set limits: %v\n", err)
os.Exit(1)
}
// Call serviceMain on Windows to handle running as a service. When
// the return isService flag is true, exit now since we ran as a
// service. Otherwise, just fall through to normal operation.
if runtime.GOOS == "windows" {
isService, err := winServiceMain()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if isService {
os.Exit(0)
}
}
2013-08-06 23:55:22 +02:00
// Work around defer not working after os.Exit()
if err := btcdMain(nil); err != nil {
2013-08-06 23:55:22 +02:00
os.Exit(1)
}
}