package main import ( "context" "flag" "fmt" "os" "sync" "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" irMetrics "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/misc" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sdnotify" "github.com/spf13/viper" "go.uber.org/zap" ) const ( // ErrorReturnCode returns when application crashed at initialization stage. ErrorReturnCode = 1 // SuccessReturnCode returns when application closed without panic. SuccessReturnCode = 0 EnvPrefix = "FROSTFS_IR" ) var ( wg = new(sync.WaitGroup) intErr = make(chan error) // internal inner ring errors logPrm = new(logger.Prm) innerRing *innerring.Server pprofCmp *pprofComponent metricsCmp *httpComponent log *logger.Logger cfg *viper.Viper configFile *string configDir *string cmode = &atomic.Bool{} audit = &atomic.Bool{} ) func exitErr(err error) { if err != nil { fmt.Println(err) os.Exit(ErrorReturnCode) } } func main() { configFile = flag.String("config", "", "path to config") configDir = flag.String("config-dir", "", "path to config directory") versionFlag := flag.Bool("version", false, "frostfs-ir node version") flag.Parse() if *versionFlag { fmt.Print(misc.BuildInfo("FrostFS Inner Ring node")) os.Exit(SuccessReturnCode) } var err error cfg, err = newConfig() exitErr(err) cmode.Store(cfg.GetBool("node.kludge_compatibility_mode")) metrics := irMetrics.NewInnerRingMetrics() err = logPrm.SetLevelString( cfg.GetString("logger.level"), ) exitErr(err) err = logPrm.SetDestination( cfg.GetString("logger.destination"), ) exitErr(err) logPrm.SamplingHook = metrics.LogMetrics().GetSamplingHook() logPrm.PrependTimestamp = cfg.GetBool("logger.timestamp") log, err = logger.NewLogger(logPrm) exitErr(err) ctx, cancel := context.WithCancel(context.Background()) pprofCmp = newPprofComponent() pprofCmp.init(ctx) metricsCmp = newMetricsComponent() metricsCmp.init(ctx) audit.Store(cfg.GetBool("audit.enabled")) innerRing, err = innerring.New(ctx, log, cfg, intErr, metrics, cmode, audit) exitErr(err) pprofCmp.start(ctx) metricsCmp.start(ctx) // start inner ring err = innerRing.Start(ctx, intErr) exitErr(err) log.Info(ctx, logs.CommonApplicationStarted, zap.String("version", misc.Version)) watchForSignal(ctx, cancel) <-ctx.Done() // graceful shutdown log.Debug(ctx, logs.FrostFSNodeWaitingForAllProcessesToStop) wg.Wait() log.Info(ctx, logs.FrostFSIRApplicationStopped) } func shutdown(ctx context.Context) { innerRing.Stop(ctx) if err := metricsCmp.shutdown(ctx); err != nil { log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer, zap.String("error", err.Error()), ) } if err := pprofCmp.shutdown(ctx); err != nil { log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer, zap.String("error", err.Error()), ) } if err := sdnotify.ClearStatus(); err != nil { log.Error(ctx, logs.FailedToReportStatusToSystemd, zap.Error(err)) } }