func blockDbPath(dbType string) string {
	dbName := blockDbNamePrefix + ".db"
	if dbType == "sqlite" {
		dbName = dbName + ".db"
	}
	dbPath := filepath.Join(cfg.Core.Datastore.Dir, dbName)
	return dbPath
}
dbPath returns the path to the block database given a database type.
package main
import (
	"fmt"
	"net"
	"net/http"
	_ "net/http/pprof"
	"os"
	"path/filepath"
	"runtime"
	"github.com/massnetorg/mass-core/blockchain/state"
	"github.com/massnetorg/mass-core/database"
	_ "github.com/massnetorg/mass-core/database/ldb"
	"github.com/massnetorg/mass-core/database/storage"
	_ "github.com/massnetorg/mass-core/database/storage/ldbstorage"
	_ "github.com/massnetorg/mass-core/database/storage/rdbstorage"
	"github.com/massnetorg/mass-core/limits"
	"github.com/massnetorg/mass-core/logging"
	"github.com/massnetorg/mass-core/trie/massdb"
	"github.com/massnetorg/mass-core/trie/rawdb"
	"github.com/massnetorg/mass-core/version"
	"massnet.org/mass-wallet/config"
	_ "massnet.org/mass-wallet/masswallet/db/ldb"
	_ "massnet.org/mass-wallet/masswallet/db/rdb"
)
var (
	cfg             *config.Config
	closeDbChannel  = make(chan struct{})
	shutdownChannel = make(chan struct{})
)
var winServiceMain func() (bool, error)
func massMain(serverChan chan<- *server) error {
	tempCfg, _, err := config.ParseConfig()
	if err != nil {
		return err
	}
	config.LoadConfig(tempCfg)
	cfg = config.CheckConfig(tempCfg)
	logging.Init(cfg.Core.Log.LogDir, config.DefaultLoggingFilename, cfg.Core.Log.LogLevel, 1, false)
	logging.CPrint(logging.INFO, fmt.Sprintf("version %s", version.GetVersion()), logging.LogFormat{})
	if cfg.Core.Metrics.ProfilePort != "" {
		go func() {
			listenAddr := net.JoinHostPort("", cfg.Core.Metrics.ProfilePort)
			logging.CPrint(logging.INFO, fmt.Sprintf("profile server listening on %s", listenAddr), logging.LogFormat{})
			profileRedirect := http.RedirectHandler("/debug/pprof",
				http.StatusSeeOther)
			http.Handle("/", profileRedirect)
			logging.CPrint(logging.ERROR, fmt.Sprintf("%v", http.ListenAndServe(listenAddr, nil)), logging.LogFormat{})
		}()
	}
	bindingDb, err := openStateDatabase(cfg.Core.Datastore.Dir, "bindingstate", 0, 0, "", false)
	if err != nil {
		logging.CPrint(logging.ERROR, "failed to load binding database", logging.LogFormat{"err": err})
		return err
	}
	db, err := setupBlockDB()
	if err != nil {
		bindingDb.Close()
		logging.CPrint(logging.ERROR, "setupBlockDB error", logging.LogFormat{"err": err})
		return err
	}
	server, err := newServer(db, state.NewDatabase(bindingDb), config.ChainParams)
	if err != nil {
		bindingDb.Close()
		db.Close()
		logging.CPrint(logging.ERROR, "unable to start server on address", logging.LogFormat{"addr": cfg.Core.P2P.ListenAddress, "err": err})
		return err
	}
	loader := NewLoader(server, config.ChainParams, cfg)
	if err = loader.LoadWallet(); err != nil {
		bindingDb.Close()
		db.Close()
		return err
	}
	addInterruptHandler(func() {
		server.Stop()
		err := loader.UnloadWallet()
		if err != nil {
			logging.CPrint(logging.ERROR, "failed to unload wallet", logging.LogFormat{"err": err})
		}
		server.WaitForShutdown()
		err0 := bindingDb.Close()
		err1 := db.Close()
		logging.CPrint(logging.INFO, "db closed", logging.LogFormat{
			"binding error": err0,
			"chain error":   err1,
		})
		closeDbChannel <- struct{}{}
	})
	server.Start()
	if serverChan != nil {
		serverChan <- server
	}
	go func() {
		shutdownChannel <- (<-closeDbChannel)
	}()
	<-shutdownChannel
	return nil
}
func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	if err := limits.SetLimits(); err != nil {
		fmt.Fprintf(os.Stderr, "failed to set limits: %v\n", err)
		os.Exit(1)
	}
	if runtime.GOOS == "windows" {
		isService, err := winServiceMain()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		if isService {
			os.Exit(0)
		}
	}
	if err := massMain(nil); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}
const blockDbNamePrefix = "blocks"