func main() { dbconfigs.RegisterFlags() flag.Parse() servenv.Init() dbConfigs, err := dbconfigs.Init("") if err != nil { log.Fatalf("Cannot initialize App dbconfig: %v", err) } if *enableRowcache { dbConfigs.App.EnableRowcache = true if *enableInvalidator { dbConfigs.App.EnableInvalidator = true } } mycnf := &mysqlctl.Mycnf{BinLogPath: *binlogPath} mysqld := mysqlctl.NewMysqld(mycnf, &dbConfigs.Dba, &dbConfigs.Repl) unmarshalFile(*overridesFile, &schemaOverrides) data, _ := json.MarshalIndent(schemaOverrides, "", " ") log.Infof("schemaOverrides: %s\n", data) ts.InitQueryService() ts.AllowQueries(&dbConfigs.App, schemaOverrides, ts.LoadCustomRules(), mysqld) log.Infof("starting vtocc %v", *servenv.Port) servenv.OnTerm(func() { ts.DisallowQueries() }) servenv.Run() }
func main() { defer exit.Recover() defer logutil.Flush() dbconfigs.RegisterFlags() flag.Parse() mycnf := mysqlctl.NewMycnf(uint32(*tabletUid), *mysqlPort) if *mysqlSocket != "" { mycnf.SocketFile = *mysqlSocket } dbcfgs, err := dbconfigs.Init(mycnf.SocketFile) if err != nil { log.Errorf("%v", err) exit.Return(255) } mysqld = mysqlctl.NewMysqld("Dba", mycnf, &dbcfgs.Dba, &dbcfgs.Repl) // Register OnTerm handler before mysqld starts, so we get notified if mysqld // dies on its own without us (or our RPC client) telling it to. mysqldTerminated := make(chan struct{}) mysqld.OnTerm(func() { close(mysqldTerminated) }) // Start or Init mysqld as needed. if _, err = os.Stat(mycnf.DataDir); os.IsNotExist(err) { log.Infof("mysql data dir (%s) doesn't exist, initializing", mycnf.DataDir) mysqld.Init(*waitTime, *bootstrapArchive, *skipSchema) } else { log.Infof("mysql data dir (%s) already exists, starting without init", mycnf.DataDir) mysqld.Start(*waitTime) } servenv.Init() defer servenv.Close() // Take mysqld down with us on SIGTERM before entering lame duck. servenv.OnTerm(func() { log.Infof("mysqlctl received SIGTERM, shutting down mysqld first") mysqld.Shutdown(false, 0) }) // Start RPC server and wait for SIGTERM. mysqlctldTerminated := make(chan struct{}) go func() { servenv.RunDefault() close(mysqlctldTerminated) }() select { case <-mysqldTerminated: log.Infof("mysqld shut down on its own, exiting mysqlctld") case <-mysqlctldTerminated: log.Infof("mysqlctld shut down gracefully") } }
func main() { defer exit.Recover() // flag parsing flags := dbconfigs.AppConfig | dbconfigs.DbaConfig | dbconfigs.FilteredConfig | dbconfigs.ReplConfig dbconfigs.RegisterFlags(flags) mysqlctl.RegisterFlags() flag.Parse() if len(flag.Args()) > 0 { flag.Usage() log.Errorf("vtcombo doesn't take any positional arguments") exit.Return(1) } // register topo server topo.RegisterServer("fakezk", zktopo.NewServer(fakezk.NewConn())) ts := topo.GetServerByName("fakezk") servenv.Init() // database configs mycnf, err := mysqlctl.NewMycnfFromFlags(0) if err != nil { log.Errorf("mycnf read failed: %v", err) exit.Return(1) } dbcfgs, err := dbconfigs.Init(mycnf.SocketFile, flags) if err != nil { log.Warning(err) } mysqld := mysqlctl.NewMysqld("Dba", "App", mycnf, &dbcfgs.Dba, &dbcfgs.App.ConnParams, &dbcfgs.Repl) // tablets configuration and init binlog.RegisterUpdateStreamService(mycnf) initTabletMap(ts, *topology, mysqld, dbcfgs, mycnf) // vtgate configuration and init resilientSrvTopoServer := vtgate.NewResilientSrvTopoServer(ts, "ResilientSrvTopoServer") healthCheck := discovery.NewHealthCheck(30*time.Second /*connTimeoutTotal*/, 1*time.Millisecond /*retryDelay*/) vtgate.Init(healthCheck, ts, resilientSrvTopoServer, nil /*schema*/, cell, 1*time.Millisecond /*retryDelay*/, 2 /*retryCount*/, 30*time.Second /*connTimeoutTotal*/, 10*time.Second /*connTimeoutPerConn*/, 365*24*time.Hour /*connLife*/, 0 /*maxInFlight*/, "" /*testGateway*/) servenv.OnTerm(func() { // FIXME(alainjobart) stop vtgate, all tablets // qsc.DisallowQueries() // agent.Stop() }) servenv.OnClose(func() { // We will still use the topo server during lameduck period // to update our state, so closing it in OnClose() topo.CloseServers() }) servenv.RunDefault() }
func main() { dbconfigs.RegisterFlags() mysqlctl.RegisterFlags() flag.Parse() if len(flag.Args()) > 0 { flag.Usage() log.Fatalf("vttablet doesn't take any positional arguments") } servenv.Init() if *tabletPath == "" { log.Fatalf("tabletPath required") } tabletAlias := tabletParamToTabletAlias(*tabletPath) mycnf, err := mysqlctl.NewMycnfFromFlags(tabletAlias.Uid) if err != nil { log.Fatalf("mycnf read failed: %v", err) } dbcfgs, err := dbconfigs.Init(mycnf.SocketFile) if err != nil { log.Warning(err) } dbcfgs.App.EnableRowcache = *enableRowcache if *tableAclConfig != "" { tableacl.Init(*tableAclConfig) } tabletserver.InitQueryService() binlog.RegisterUpdateStreamService(mycnf) // Depends on both query and updateStream. agent, err = tabletmanager.NewActionAgent(tabletAlias, dbcfgs, mycnf, *servenv.Port, *servenv.SecurePort, *overridesFile) if err != nil { log.Fatal(err) } tabletmanager.HttpHandleSnapshots(mycnf, tabletAlias.Uid) servenv.OnTerm(func() { tabletserver.DisallowQueries() binlog.DisableUpdateStreamService() agent.Stop() }) servenv.OnClose(func() { // We will still use the topo server during lameduck period // to update our state, so closing it in OnClose() topo.CloseServers() }) servenv.RunDefault() }
func main() { dbconfigs.RegisterFlags() flag.Parse() servenv.Init() if *tabletPath == "" { log.Fatalf("tabletPath required") } tabletAlias := vttablet.TabletParamToTabletAlias(*tabletPath) if *mycnfFile == "" { *mycnfFile = mysqlctl.MycnfFile(tabletAlias.Uid) } mycnf, err := mysqlctl.ReadMycnf(*mycnfFile) if err != nil { log.Fatalf("mycnf read failed: %v", err) } dbcfgs, err := dbconfigs.Init(mycnf.SocketFile) if err != nil { log.Warning(err) } dbcfgs.App.EnableRowcache = *enableRowcache ts.InitQueryService() binlog.RegisterUpdateStreamService(mycnf) // Depends on both query and updateStream. agent, err = vttablet.InitAgent(tabletAlias, dbcfgs, mycnf, *servenv.Port, *servenv.SecurePort, *overridesFile) if err != nil { log.Fatal(err) } vttablet.HttpHandleSnapshots(mycnf, tabletAlias.Uid) servenv.OnTerm(func() { ts.DisallowQueries() binlog.DisableUpdateStreamService() topo.CloseServers() agent.Stop() }) servenv.Run() }
func main() { dbconfigs.RegisterFlags() flag.Parse() if len(flag.Args()) > 0 { flag.Usage() log.Fatalf("vtocc doesn't take any positional arguments") } servenv.Init() dbConfigs, err := dbconfigs.Init("") if err != nil { log.Fatalf("Cannot initialize App dbconfig: %v", err) } if *enableRowcache { dbConfigs.App.EnableRowcache = true if *enableInvalidator { dbConfigs.App.EnableInvalidator = true } } mycnf := &mysqlctl.Mycnf{BinLogPath: *binlogPath} mysqld := mysqlctl.NewMysqld("Dba", mycnf, &dbConfigs.Dba, &dbConfigs.Repl) unmarshalFile(*overridesFile, &schemaOverrides) data, _ := json.MarshalIndent(schemaOverrides, "", " ") log.Infof("schemaOverrides: %s\n", data) if *tableAclConfig != "" { tableacl.Init(*tableAclConfig) } tabletserver.InitQueryService() err = tabletserver.AllowQueries(&dbConfigs.App, schemaOverrides, tabletserver.LoadCustomRules(), mysqld, true) if err != nil { return } log.Infof("starting vtocc %v", *servenv.Port) servenv.OnTerm(func() { tabletserver.DisallowQueries() mysqld.Close() }) servenv.RunDefault() }
func (agent *ActionAgent) initHeathCheck() { if !agent.IsRunningHealthCheck() { log.Infof("No target_tablet_type specified, disabling any health check") return } log.Infof("Starting periodic health check every %v with target_tablet_type=%v", *healthCheckInterval, *targetTabletType) t := timer.NewTimer(*healthCheckInterval) servenv.OnTerm(func() { // When we enter lameduck mode, we want to not call // the health check any more. After this returns, we // are guaranteed to not call it. log.Info("Stopping periodic health check timer") t.Stop() // Now we can finish up and force ourselves to not healthy. agent.terminateHealthChecks(topo.TabletType(*targetTabletType)) }) t.Start(func() { agent.runHealthCheck(topo.TabletType(*targetTabletType)) }) }
func main() { defer exit.Recover() defer logutil.Flush() dbconfigFlags := dbconfigs.AppConfig | dbconfigs.DbaConfig | dbconfigs.FilteredConfig | dbconfigs.ReplConfig dbconfigs.RegisterFlags(dbconfigFlags) flag.Parse() // We'll register this OnTerm handler before mysqld starts, so we get notified // if mysqld dies on its own without us (or our RPC client) telling it to. mysqldTerminated := make(chan struct{}) onTermFunc := func() { close(mysqldTerminated) } // Start or Init mysqld as needed. ctx, cancel := context.WithTimeout(context.Background(), *waitTime) tabletDir := mysqlctl.TabletDir(uint32(*tabletUID)) if _, statErr := os.Stat(tabletDir); os.IsNotExist(statErr) { // Generate my.cnf from scratch and use it to find mysqld. log.Infof("tablet dir (%s) doesn't exist, initializing", tabletDir) var err error mysqld, err = mysqlctl.CreateMysqld(uint32(*tabletUID), *mysqlSocket, int32(*mysqlPort), dbconfigFlags) if err != nil { log.Errorf("failed to initialize mysql config: %v", err) exit.Return(1) } mysqld.OnTerm(onTermFunc) if err := mysqld.Init(ctx, *initDBSQLFile); err != nil { log.Errorf("failed to initialize mysql data dir and start mysqld: %v", err) exit.Return(1) } } else { // There ought to be an existing my.cnf, so use it to find mysqld. log.Infof("tablet dir (%s) already exists, starting without init", tabletDir) var err error mysqld, err = mysqlctl.OpenMysqld(uint32(*tabletUID), dbconfigFlags) if err != nil { log.Errorf("failed to find mysql config: %v", err) exit.Return(1) } mysqld.OnTerm(onTermFunc) if err := mysqld.Start(ctx); err != nil { log.Errorf("failed to start mysqld: %v", err) exit.Return(1) } } cancel() servenv.Init() defer servenv.Close() // Take mysqld down with us on SIGTERM before entering lame duck. servenv.OnTerm(func() { log.Infof("mysqlctl received SIGTERM, shutting down mysqld first") ctx := context.Background() mysqld.Shutdown(ctx, false) }) // Start RPC server and wait for SIGTERM. mysqlctldTerminated := make(chan struct{}) go func() { servenv.RunDefault() close(mysqlctldTerminated) }() select { case <-mysqldTerminated: log.Infof("mysqld shut down on its own, exiting mysqlctld") case <-mysqlctldTerminated: log.Infof("mysqlctld shut down gracefully") } }
func main() { defer exit.Recover() flags := dbconfigs.AppConfig | dbconfigs.DbaConfig | dbconfigs.FilteredConfig | dbconfigs.ReplConfig dbconfigs.RegisterFlags(flags) mysqlctl.RegisterFlags() flag.Parse() tabletserver.Init() if len(flag.Args()) > 0 { flag.Usage() log.Errorf("vttablet doesn't take any positional arguments") exit.Return(1) } servenv.Init() if *tabletPath == "" { log.Errorf("tabletPath required") exit.Return(1) } tabletAlias, err := topoproto.ParseTabletAlias(*tabletPath) if err != nil { log.Error(err) exit.Return(1) } mycnf, err := mysqlctl.NewMycnfFromFlags(tabletAlias.Uid) if err != nil { log.Errorf("mycnf read failed: %v", err) exit.Return(1) } dbcfgs, err := dbconfigs.Init(mycnf.SocketFile, flags) if err != nil { log.Warning(err) } dbcfgs.App.EnableRowcache = *enableRowcache // creates and registers the query service qsc := tabletserver.NewServer() qsc.Register() binlog.RegisterUpdateStreamService(mycnf) if *tableAclConfig != "" { tableacl.Register("simpleacl", &simpleacl.Factory{}) tableacl.Init( *tableAclConfig, func() { qsc.ClearQueryPlanCache() }, ) } else if *enforceTableACLConfig { log.Error("table acl config has to be specified with table-acl-config flag because enforce-tableacl-config is set.") exit.Return(1) } // Create mysqld and register the health reporter (needs to be done // before initializing the agent, so the initial health check // done by the agent has the right reporter) mysqld := mysqlctl.NewMysqld("Dba", "App", mycnf, &dbcfgs.Dba, &dbcfgs.App.ConnParams, &dbcfgs.Repl) registerHealthReporter(mysqld) // Depends on both query and updateStream. gRPCPort := int32(0) if servenv.GRPCPort != nil { gRPCPort = int32(*servenv.GRPCPort) } agent, err = tabletmanager.NewActionAgent(context.Background(), mysqld, qsc, tabletAlias, dbcfgs, mycnf, int32(*servenv.Port), gRPCPort, *overridesFile, *lockTimeout) if err != nil { log.Error(err) exit.Return(1) } servenv.OnRun(func() { addStatusParts(qsc) }) servenv.OnTerm(func() { qsc.StopService() binlog.DisableUpdateStreamService() agent.Stop() }) servenv.OnClose(func() { // We will still use the topo server during lameduck period // to update our state, so closing it in OnClose() topo.CloseServers() }) servenv.RunDefault() }
func init() { tabletserver.QueryServiceControlRegisterFunctions = append(tabletserver.QueryServiceControlRegisterFunctions, ActivateZkCustomRules) servenv.OnTerm(zkCustomRule.Close) }
// Start validates and updates the topology records for the tablet, and performs // the initial state change callback to start tablet services. // If initUpdateStream is set, update stream service will also be registered. func (agent *ActionAgent) Start(ctx context.Context, mysqlPort, vtPort, gRPCPort int32, initUpdateStream bool) error { var err error if _, err = agent.updateTabletFromTopo(ctx); err != nil { return err } // find our hostname as fully qualified, and IP hostname := *tabletHostname if hostname == "" { hostname, err = netutil.FullyQualifiedHostname() if err != nil { return err } } ipAddrs, err := net.LookupHost(hostname) if err != nil { return err } ipAddr := ipAddrs[0] // Update bind addr for mysql and query service in the tablet node. f := func(tablet *topodatapb.Tablet) error { tablet.Hostname = hostname tablet.Ip = ipAddr if tablet.PortMap == nil { tablet.PortMap = make(map[string]int32) } if mysqlPort != 0 { // only overwrite mysql port if we know it, otherwise // leave it as is. tablet.PortMap["mysql"] = mysqlPort } if vtPort != 0 { tablet.PortMap["vt"] = vtPort } else { delete(tablet.PortMap, "vt") } delete(tablet.PortMap, "vts") if gRPCPort != 0 { tablet.PortMap["grpc"] = gRPCPort } else { delete(tablet.PortMap, "grpc") } return nil } if _, err := agent.TopoServer.UpdateTabletFields(ctx, agent.Tablet().Alias, f); err != nil { return err } // Reread to get the changes we just made tablet, err := agent.updateTabletFromTopo(ctx) if err != nil { return err } // Save the original tablet record as it is now (at startup). agent.initialTablet = proto.Clone(tablet).(*topodatapb.Tablet) if err = agent.verifyTopology(ctx); err != nil { return err } if err = agent.verifyServingAddrs(ctx); err != nil { return err } // get and fix the dbname if necessary if !agent.DBConfigs.IsZero() { // Only for real instances // Update our DB config to match the info we have in the tablet if agent.DBConfigs.App.DbName == "" { agent.DBConfigs.App.DbName = topoproto.TabletDbName(tablet) } if agent.DBConfigs.Filtered.DbName == "" { agent.DBConfigs.Filtered.DbName = topoproto.TabletDbName(tablet) } agent.DBConfigs.App.Keyspace = tablet.Keyspace agent.DBConfigs.App.Shard = tablet.Shard } // create and register the RPC services from UpdateStream // (it needs the dbname, so it has to be delayed up to here, // but it has to be before updateState below that may use it) if initUpdateStream { us := binlog.NewUpdateStream(agent.MysqlDaemon, agent.DBConfigs.App.DbName) us.RegisterService() agent.UpdateStream = us } servenv.OnTerm(func() { // Disable UpdateStream (if any) upon entering lameduck. // We do this regardless of initUpdateStream, since agent.UpdateStream // may have been set from elsewhere. if agent.UpdateStream != nil { agent.UpdateStream.Disable() } }) // initialize tablet server if err := agent.QueryServiceControl.InitDBConfig(querypb.Target{ Keyspace: tablet.Keyspace, Shard: tablet.Shard, TabletType: tablet.Type, }, agent.DBConfigs, agent.SchemaOverrides, agent.MysqlDaemon); err != nil { return fmt.Errorf("failed to InitDBConfig: %v", err) } // export a few static variables if agent.exportStats { statsKeyspace := stats.NewString("TabletKeyspace") statsShard := stats.NewString("TabletShard") statsKeyRangeStart := stats.NewString("TabletKeyRangeStart") statsKeyRangeEnd := stats.NewString("TabletKeyRangeEnd") statsKeyspace.Set(tablet.Keyspace) statsShard.Set(tablet.Shard) if key.KeyRangeIsPartial(tablet.KeyRange) { statsKeyRangeStart.Set(hex.EncodeToString(tablet.KeyRange.Start)) statsKeyRangeEnd.Set(hex.EncodeToString(tablet.KeyRange.End)) } } // initialize the key range query rule if err := agent.initializeKeyRangeRule(ctx, tablet.Keyspace, tablet.KeyRange); err != nil { return err } // update our state oldTablet := &topodatapb.Tablet{} if err = agent.updateState(ctx, oldTablet, "Start"); err != nil { log.Warningf("Initial updateState failed, will need a state change before running properly: %v", err) } // run a background task to rebuild the SrvKeyspace in our cell/keyspace // if it doesn't exist yet go agent.maybeRebuildKeyspace(tablet.Alias.Cell, tablet.Keyspace) return nil }
func main() { defer exit.Recover() defer logutil.Flush() flags := dbconfigs.AppConfig | dbconfigs.DbaConfig | dbconfigs.FilteredConfig | dbconfigs.ReplConfig dbconfigs.RegisterFlags(flags) flag.Parse() mycnf := mysqlctl.NewMycnf(uint32(*tabletUID), int32(*mysqlPort)) if *mysqlSocket != "" { mycnf.SocketFile = *mysqlSocket } dbcfgs, err := dbconfigs.Init(mycnf.SocketFile, flags) if err != nil { log.Errorf("%v", err) exit.Return(255) } mysqld = mysqlctl.NewMysqld("Dba", "App", mycnf, &dbcfgs.Dba, &dbcfgs.App.ConnParams, &dbcfgs.Repl) // Register OnTerm handler before mysqld starts, so we get notified if mysqld // dies on its own without us (or our RPC client) telling it to. mysqldTerminated := make(chan struct{}) mysqld.OnTerm(func() { close(mysqldTerminated) }) // Start or Init mysqld as needed. ctx, cancel := context.WithTimeout(context.Background(), *waitTime) if _, err = os.Stat(mycnf.DataDir); os.IsNotExist(err) { log.Infof("mysql data dir (%s) doesn't exist, initializing", mycnf.DataDir) mysqld.Init(ctx, *initDBSQLFile) } else { log.Infof("mysql data dir (%s) already exists, starting without init", mycnf.DataDir) mysqld.Start(ctx) } cancel() servenv.Init() defer servenv.Close() // Take mysqld down with us on SIGTERM before entering lame duck. servenv.OnTerm(func() { log.Infof("mysqlctl received SIGTERM, shutting down mysqld first") ctx := context.Background() mysqld.Shutdown(ctx, false) }) // Start RPC server and wait for SIGTERM. mysqlctldTerminated := make(chan struct{}) go func() { servenv.RunDefault() close(mysqlctldTerminated) }() select { case <-mysqldTerminated: log.Infof("mysqld shut down on its own, exiting mysqlctld") case <-mysqlctldTerminated: log.Infof("mysqlctld shut down gracefully") } }
func main() { defer exit.Recover() // flag parsing flags := dbconfigs.AppConfig | dbconfigs.DbaConfig | dbconfigs.FilteredConfig | dbconfigs.ReplConfig dbconfigs.RegisterFlags(flags) mysqlctl.RegisterFlags() flag.Parse() if len(flag.Args()) > 0 { flag.Usage() log.Errorf("vtcombo doesn't take any positional arguments") exit.Return(1) } // register topo server zkconn := fakezk.NewConn() topo.RegisterServer("fakezk", zktopo.NewServer(zkconn)) ts = topo.GetServerByName("fakezk") servenv.Init() tabletserver.Init() // database configs mycnf, err := mysqlctl.NewMycnfFromFlags(0) if err != nil { log.Errorf("mycnf read failed: %v", err) exit.Return(1) } dbcfgs, err := dbconfigs.Init(mycnf.SocketFile, flags) if err != nil { log.Warning(err) } mysqld := mysqlctl.NewMysqld("Dba", "App", mycnf, &dbcfgs.Dba, &dbcfgs.App.ConnParams, &dbcfgs.Repl) servenv.OnClose(mysqld.Close) // tablets configuration and init initTabletMap(ts, *topology, mysqld, dbcfgs, mycnf) // vschema var schema *planbuilder.Schema if *vschema != "" { schema, err = planbuilder.LoadFile(*vschema) if err != nil { log.Error(err) exit.Return(1) } log.Infof("v3 is enabled: loaded schema from file") } // vtgate configuration and init resilientSrvTopoServer := vtgate.NewResilientSrvTopoServer(ts, "ResilientSrvTopoServer") healthCheck := discovery.NewHealthCheck(30*time.Second /*connTimeoutTotal*/, 1*time.Millisecond /*retryDelay*/, 1*time.Minute /*healthCheckTimeout*/) tabletTypesToWait := []topodatapb.TabletType{ topodatapb.TabletType_MASTER, topodatapb.TabletType_REPLICA, topodatapb.TabletType_RDONLY, } vtgate.Init(healthCheck, ts, resilientSrvTopoServer, schema, cell, 1*time.Millisecond /*retryDelay*/, 2 /*retryCount*/, 30*time.Second /*connTimeoutTotal*/, 10*time.Second /*connTimeoutPerConn*/, 365*24*time.Hour /*connLife*/, tabletTypesToWait, 0 /*maxInFlight*/, "" /*testGateway*/) // vtctld configuration and init vtctld.InitVtctld(ts) vtctld.HandleExplorer("zk", zktopo.NewZkExplorer(zkconn)) servenv.OnTerm(func() { // FIXME(alainjobart): stop vtgate }) servenv.OnClose(func() { log.Infof("Total count of new connections to MySQL: %v", expvar.Get("mysql-new-connection-count")) // We will still use the topo server during lameduck period // to update our state, so closing it in OnClose() topo.CloseServers() }) servenv.RunDefault() }
// NewActionAgent creates a new ActionAgent and registers all the // associated services. // // batchCtx is the context that the agent will use for any background tasks // it spawns. func NewActionAgent( batchCtx context.Context, mysqld mysqlctl.MysqlDaemon, queryServiceControl tabletserver.Controller, tabletAlias *topodatapb.TabletAlias, dbcfgs dbconfigs.DBConfigs, mycnf *mysqlctl.Mycnf, port, gRPCPort int32, overridesFile string, ) (agent *ActionAgent, err error) { schemaOverrides := loadSchemaOverrides(overridesFile) topoServer := topo.GetServer() agent = &ActionAgent{ QueryServiceControl: queryServiceControl, HealthReporter: health.DefaultAggregator, batchCtx: batchCtx, TopoServer: topoServer, TabletAlias: tabletAlias, MysqlDaemon: mysqld, DBConfigs: dbcfgs, SchemaOverrides: schemaOverrides, History: history.New(historyLength), lastHealthMapCount: stats.NewInt("LastHealthMapCount"), _healthy: fmt.Errorf("healthcheck not run yet"), } agent.registerQueryRuleSources() // try to initialize the tablet if we have to if err := agent.InitTablet(port, gRPCPort); err != nil { return nil, fmt.Errorf("agent.InitTablet failed: %v", err) } // Publish and set the TargetTabletType. Not a global var // since it should never be changed. statsTabletType := stats.NewString("TargetTabletType") statsTabletType.Set(*targetTabletType) // Create the TabletType stats agent.exportStats = true agent.statsTabletType = stats.NewString("TabletType") // Start the binlog player services, not playing at start. agent.BinlogPlayerMap = NewBinlogPlayerMap(topoServer, mysqld, func() binlogplayer.VtClient { return binlogplayer.NewDbClient(&agent.DBConfigs.Filtered) }) // Stop all binlog players upon entering lameduck. servenv.OnTerm(agent.BinlogPlayerMap.StopAllPlayersAndReset) RegisterBinlogPlayerMap(agent.BinlogPlayerMap) // try to figure out the mysql port mysqlPort := mycnf.MysqlPort if mysqlPort == 0 { // we don't know the port, try to get it from mysqld var err error mysqlPort, err = mysqld.GetMysqlPort() if err != nil { log.Warningf("Cannot get current mysql port, will use 0 for now: %v", err) } } // Start will get the tablet info, and update our state from it if err := agent.Start(batchCtx, int32(mysqlPort), port, gRPCPort, true); err != nil { return nil, err } // register the RPC services from the agent agent.registerQueryService() // two cases then: // - restoreFromBackup is set: we restore, then initHealthCheck, all // in the background // - restoreFromBackup is not set: we initHealthCheck right away if *restoreFromBackup { go func() { // restoreFromBackup wil just be a regular action // (same as if it was triggered remotely) if err := agent.RestoreFromBackup(batchCtx); err != nil { println(fmt.Sprintf("RestoreFromBackup failed: %v", err)) log.Fatalf("RestoreFromBackup failed: %v", err) } // after the restore is done, start health check agent.initHealthCheck() }() } else { // synchronously start health check if needed agent.initHealthCheck() } return agent, nil }
func main() { defer exit.Recover() // flag parsing flags := dbconfigs.AppConfig | dbconfigs.DbaConfig | dbconfigs.FilteredConfig | dbconfigs.ReplConfig dbconfigs.RegisterFlags(flags) mysqlctl.RegisterFlags() flag.Parse() if len(flag.Args()) > 0 { flag.Usage() log.Errorf("vtcombo doesn't take any positional arguments") exit.Return(1) } // set discoverygateway flag to default value flag.Set("cells_to_watch", cell) // register topo server zkconn := fakezk.NewConn() topo.RegisterServer("fakezk", zktopo.NewServer(zkconn)) ts = topo.GetServerByName("fakezk") servenv.Init() tabletserver.Init() // database configs mycnf, err := mysqlctl.NewMycnfFromFlags(0) if err != nil { log.Errorf("mycnf read failed: %v", err) exit.Return(1) } dbcfgs, err := dbconfigs.Init(mycnf.SocketFile, flags) if err != nil { log.Warning(err) } mysqld := mysqlctl.NewMysqld("Dba", "App", mycnf, &dbcfgs.Dba, &dbcfgs.App.ConnParams, &dbcfgs.Repl) servenv.OnClose(mysqld.Close) // tablets configuration and init if err := initTabletMap(ts, *protoTopo, mysqld, dbcfgs, *schemaDir, mycnf); err != nil { log.Errorf("initTabletMapProto failed: %v", err) exit.Return(1) } // vtgate configuration and init resilientSrvTopoServer := vtgate.NewResilientSrvTopoServer(ts, "ResilientSrvTopoServer") healthCheck := discovery.NewHealthCheck(30*time.Second /*connTimeoutTotal*/, 1*time.Millisecond /*retryDelay*/, 1*time.Hour /*healthCheckTimeout*/) tabletTypesToWait := []topodatapb.TabletType{ topodatapb.TabletType_MASTER, topodatapb.TabletType_REPLICA, topodatapb.TabletType_RDONLY, } vtgate.Init(context.Background(), healthCheck, ts, resilientSrvTopoServer, cell, 2 /*retryCount*/, tabletTypesToWait) // vtctld configuration and init vtctld.InitVtctld(ts) vtctld.HandleExplorer("zk", zktopo.NewZkExplorer(zkconn)) servenv.OnTerm(func() { // FIXME(alainjobart): stop vtgate }) servenv.OnClose(func() { // We will still use the topo server during lameduck period // to update our state, so closing it in OnClose() topo.CloseServers() }) servenv.RunDefault() }
func main() { defer exit.Recover() // flag parsing flags := dbconfigs.AppConfig | dbconfigs.AllPrivsConfig | dbconfigs.DbaConfig | dbconfigs.FilteredConfig | dbconfigs.ReplConfig dbconfigs.RegisterFlags(flags) mysqlctl.RegisterFlags() flag.Parse() if len(flag.Args()) > 0 { flag.Usage() log.Errorf("vtcombo doesn't take any positional arguments") exit.Return(1) } // parse the input topology tpb := &vttestpb.VTTestTopology{} if err := proto.UnmarshalText(*protoTopo, tpb); err != nil { log.Errorf("cannot parse topology: %v", err) exit.Return(1) } // default cell to "test" if unspecified if len(tpb.Cells) == 0 { tpb.Cells = append(tpb.Cells, "test") } // set discoverygateway flag to default value flag.Set("cells_to_watch", strings.Join(tpb.Cells, ",")) // vtctld UI requires the cell flag flag.Set("cell", tpb.Cells[0]) flag.Set("enable_realtime_stats", "true") flag.Set("log_dir", "$VTDATAROOT/tmp") // create zk client config file config := path.Join(os.Getenv("VTDATAROOT"), "vt_0000000001/tmp/test-zk-client-conf.json") cellmap := make(map[string]string) for _, cell := range tpb.Cells { cellmap[cell] = "localhost" } b, err := json.Marshal(cellmap) if err != nil { log.Errorf("failed to marshal json: %v", err) } f, err := os.Create(config) if err != nil { log.Errorf("failed to create zk config file: %v", err) } defer f.Close() _, err = f.WriteString(string(b[:])) if err != nil { log.Errorf("failed to write to zk config file: %v", err) } os.Setenv("ZK_CLIENT_CONFIG", config) // register topo server zkconn := fakezk.NewConn() topo.RegisterServer("fakezk", zktopo.NewServer(zkconn)) ts = topo.GetServerByName("fakezk") servenv.Init() tabletserver.Init() // database configs mycnf, err := mysqlctl.NewMycnfFromFlags(0) if err != nil { log.Errorf("mycnf read failed: %v", err) exit.Return(1) } dbcfgs, err := dbconfigs.Init(mycnf.SocketFile, flags) if err != nil { log.Warning(err) } mysqld := mysqlctl.NewMysqld(mycnf, &dbcfgs.Dba, &dbcfgs.AllPrivs, &dbcfgs.App, &dbcfgs.Repl, true /* enablePublishStats */) servenv.OnClose(mysqld.Close) // tablets configuration and init if err := initTabletMap(ts, tpb, mysqld, dbcfgs, *schemaDir, mycnf); err != nil { log.Errorf("initTabletMapProto failed: %v", err) exit.Return(1) } // vtgate configuration and init resilientSrvTopoServer := vtgate.NewResilientSrvTopoServer(ts, "ResilientSrvTopoServer") healthCheck := discovery.NewHealthCheck(30*time.Second /*connTimeoutTotal*/, 1*time.Millisecond /*retryDelay*/, 1*time.Hour /*healthCheckTimeout*/) tabletTypesToWait := []topodatapb.TabletType{ topodatapb.TabletType_MASTER, topodatapb.TabletType_REPLICA, topodatapb.TabletType_RDONLY, } vtgate.Init(context.Background(), healthCheck, ts, resilientSrvTopoServer, tpb.Cells[0], 2 /*retryCount*/, tabletTypesToWait) // vtctld configuration and init vtctld.InitVtctld(ts) vtctld.HandleExplorer("zk", zktopo.NewZkExplorer(zkconn)) servenv.OnTerm(func() { // FIXME(alainjobart): stop vtgate }) servenv.OnClose(func() { // We will still use the topo server during lameduck period // to update our state, so closing it in OnClose() topo.CloseServers() }) servenv.RunDefault() }
// NewActionAgent creates a new ActionAgent and registers all the // associated services. // // batchCtx is the context that the agent will use for any background tasks // it spawns. func NewActionAgent( batchCtx context.Context, mysqld mysqlctl.MysqlDaemon, queryServiceControl tabletserver.Controller, tabletAlias *topodatapb.TabletAlias, dbcfgs dbconfigs.DBConfigs, mycnf *mysqlctl.Mycnf, port, gRPCPort int32, ) (agent *ActionAgent, err error) { topoServer := topo.GetServer() orc, err := newOrcClient() if err != nil { return nil, err } agent = &ActionAgent{ QueryServiceControl: queryServiceControl, HealthReporter: health.DefaultAggregator, batchCtx: batchCtx, TopoServer: topoServer, TabletAlias: tabletAlias, MysqlDaemon: mysqld, DBConfigs: dbcfgs, History: history.New(historyLength), _healthy: fmt.Errorf("healthcheck not run yet"), orc: orc, } agent.registerQueryRuleSources() // try to initialize the tablet if we have to if err := agent.InitTablet(port, gRPCPort); err != nil { return nil, fmt.Errorf("agent.InitTablet failed: %v", err) } // Create the TabletType stats agent.exportStats = true agent.statsTabletType = stats.NewString("TabletType") // Start the binlog player services, not playing at start. agent.BinlogPlayerMap = NewBinlogPlayerMap(topoServer, mysqld, func() binlogplayer.VtClient { return binlogplayer.NewDbClient(&agent.DBConfigs.Filtered) }) // Stop all binlog players upon entering lameduck. servenv.OnTerm(agent.BinlogPlayerMap.StopAllPlayersAndReset) RegisterBinlogPlayerMap(agent.BinlogPlayerMap) // try to figure out the mysql port mysqlPort := mycnf.MysqlPort if mysqlPort == 0 { // we don't know the port, try to get it from mysqld var err error mysqlPort, err = mysqld.GetMysqlPort() if err != nil { log.Warningf("Cannot get current mysql port, will use 0 for now: %v", err) } } // Start will get the tablet info, and update our state from it if err := agent.Start(batchCtx, int32(mysqlPort), port, gRPCPort, true); err != nil { return nil, err } // register the RPC services from the agent servenv.OnRun(func() { agent.registerQueryService() }) // two cases then: // - restoreFromBackup is set: we restore, then initHealthCheck, all // in the background // - restoreFromBackup is not set: we initHealthCheck right away if *restoreFromBackup { go func() { // restoreFromBackup wil just be a regular action // (same as if it was triggered remotely) if err := agent.RestoreData(batchCtx, logutil.NewConsoleLogger(), false /* deleteBeforeRestore */); err != nil { println(fmt.Sprintf("RestoreFromBackup failed: %v", err)) log.Fatalf("RestoreFromBackup failed: %v", err) } // after the restore is done, start health check agent.initHealthCheck() }() } else { // update our state if err := agent.refreshTablet(batchCtx, "Start"); err != nil { return nil, err } // synchronously start health check if needed agent.initHealthCheck() } // Start periodic Orchestrator self-registration, if configured. if agent.orc != nil { go agent.orc.DiscoverLoop(agent) } return agent, nil }
func main() { defer exit.Recover() flags := dbconfigs.AppConfig | dbconfigs.DbaConfig | dbconfigs.FilteredConfig | dbconfigs.ReplConfig dbconfigs.RegisterFlags(flags) flag.Parse() if len(flag.Args()) > 0 { flag.Usage() log.Errorf("vtocc doesn't take any positional arguments") exit.Return(1) } servenv.Init() dbConfigs, err := dbconfigs.Init("", flags) if err != nil { log.Errorf("Cannot initialize App dbconfig: %v", err) exit.Return(1) } if *enableRowcache { dbConfigs.App.EnableRowcache = true if *enableInvalidator { dbConfigs.App.EnableInvalidator = true } } mycnf := &mysqlctl.Mycnf{BinLogPath: *binlogPath} mysqld := mysqlctl.NewMysqld("Dba", "App", mycnf, &dbConfigs.Dba, &dbConfigs.App.ConnParams, &dbConfigs.Repl) if err := unmarshalFile(*overridesFile, &schemaOverrides); err != nil { log.Error(err) exit.Return(1) } data, _ := json.MarshalIndent(schemaOverrides, "", " ") log.Infof("schemaOverrides: %s\n", data) if *tableAclConfig != "" { tableacl.Register("simpleacl", &simpleacl.Factory{}) tableacl.Init(*tableAclConfig) } qsc := tabletserver.NewQueryServiceControl() tabletserver.InitQueryService(qsc) // Query service can go into NOT_SERVING state if mysql goes down. // So, continuously retry starting the service. So, it tries to come // back up if it went down. go func() { for { _ = qsc.AllowQueries(nil, dbConfigs, schemaOverrides, mysqld) time.Sleep(30 * time.Second) } }() log.Infof("starting vtocc %v", *servenv.Port) servenv.OnRun(func() { addStatusParts(qsc) }) servenv.OnTerm(func() { qsc.DisallowQueries() mysqld.Close() }) servenv.RunDefault() }
// Start validates and updates the topology records for the tablet, and performs // the initial state change callback to start tablet services. // If initUpdateStream is set, update stream service will also be registered. func (agent *ActionAgent) Start(ctx context.Context, mysqlPort, vtPort, gRPCPort int32, initUpdateStream bool) error { // find our hostname as fully qualified, and IP hostname := *tabletHostname if hostname == "" { var err error hostname, err = netutil.FullyQualifiedHostname() if err != nil { return err } } ipAddrs, err := net.LookupHost(hostname) if err != nil { return err } ipAddr := ipAddrs[0] // Update bind addr for mysql and query service in the tablet node. f := func(tablet *topodatapb.Tablet) error { tablet.Hostname = hostname tablet.Ip = ipAddr if tablet.PortMap == nil { tablet.PortMap = make(map[string]int32) } if mysqlPort != 0 { // only overwrite mysql port if we know it, otherwise // leave it as is. tablet.PortMap["mysql"] = mysqlPort } if vtPort != 0 { tablet.PortMap["vt"] = vtPort } else { delete(tablet.PortMap, "vt") } delete(tablet.PortMap, "vts") if gRPCPort != 0 { tablet.PortMap["grpc"] = gRPCPort } else { delete(tablet.PortMap, "grpc") } // Save the original tablet for ownership tests later. agent.initialTablet = tablet return nil } if _, err := agent.TopoServer.UpdateTabletFields(ctx, agent.TabletAlias, f); err != nil { return err } // Verify the topology is correct. agent.verifyTopology(ctx) // Get and fix the dbname if necessary, only for real instances. if !agent.DBConfigs.IsZero() { dbname := topoproto.TabletDbName(agent.initialTablet) // Update our DB config to match the info we have in the tablet if agent.DBConfigs.App.DbName == "" { agent.DBConfigs.App.DbName = dbname } if agent.DBConfigs.Filtered.DbName == "" { agent.DBConfigs.Filtered.DbName = dbname } } // create and register the RPC services from UpdateStream // (it needs the dbname, so it has to be delayed up to here, // but it has to be before updateState below that may use it) if initUpdateStream { us := binlog.NewUpdateStream(agent.MysqlDaemon, agent.DBConfigs.App.DbName) agent.UpdateStream = us servenv.OnRun(func() { us.RegisterService() }) } servenv.OnTerm(func() { // Disable UpdateStream (if any) upon entering lameduck. // We do this regardless of initUpdateStream, since agent.UpdateStream // may have been set from elsewhere. if agent.UpdateStream != nil { agent.UpdateStream.Disable() } }) // initialize tablet server if err := agent.QueryServiceControl.InitDBConfig(querypb.Target{ Keyspace: agent.initialTablet.Keyspace, Shard: agent.initialTablet.Shard, TabletType: agent.initialTablet.Type, }, agent.DBConfigs, agent.MysqlDaemon); err != nil { return fmt.Errorf("failed to InitDBConfig: %v", err) } // export a few static variables if agent.exportStats { statsKeyspace := stats.NewString("TabletKeyspace") statsShard := stats.NewString("TabletShard") statsKeyRangeStart := stats.NewString("TabletKeyRangeStart") statsKeyRangeEnd := stats.NewString("TabletKeyRangeEnd") statsKeyspace.Set(agent.initialTablet.Keyspace) statsShard.Set(agent.initialTablet.Shard) if key.KeyRangeIsPartial(agent.initialTablet.KeyRange) { statsKeyRangeStart.Set(hex.EncodeToString(agent.initialTablet.KeyRange.Start)) statsKeyRangeEnd.Set(hex.EncodeToString(agent.initialTablet.KeyRange.End)) } } // Initialize the current tablet to match our current running // state: Has most field filled in, but type is UNKNOWN. // Subsequents calls to updateState or refreshTablet // will then work as expected. startingTablet := proto.Clone(agent.initialTablet).(*topodatapb.Tablet) startingTablet.Type = topodatapb.TabletType_UNKNOWN agent.setTablet(startingTablet) // run a background task to rebuild the SrvKeyspace in our cell/keyspace // if it doesn't exist yet go agent.maybeRebuildKeyspace(agent.initialTablet.Alias.Cell, agent.initialTablet.Keyspace) return nil }