func init() { servenv.OnRun(func() { if servenv.GRPCCheckServiceMap("throttler") { StartServer(servenv.GRPCServer, throttler.GlobalManager) } }) }
func init() { servenv.OnRun(func() { if *allowedReplicationLag > 0 { health.Register("replication_reporter", mysqlctl.MySQLReplicationLag(agent.Mysqld, *allowedReplicationLag)) } }) }
func init() { servenv.OnRun(func() { servenv.AddStatusPart("Topology Cache", topoTemplate, func() interface{} { return resilientSrvTopoServer.CacheStatus() }) }) }
func init() { servenv.OnRun(func() { servenv.AddStatusPart("Tablet", tabletTemplate, func() interface{} { return map[string]interface{}{ "Tablet": agent.Tablet(), "BlacklistedTables": agent.BlacklistedTables(), } }) if agent.IsRunningHealthCheck() { servenv.AddStatusFuncs(template.FuncMap{ "github_com_youtube_vitess_health_html_name": healthHTMLName, }) servenv.AddStatusPart("Health", healthTemplate, func() interface{} { return &healthStatus{Records: agent.History.Records()} }) } tabletserver.AddStatusPart() servenv.AddStatusPart("Binlog Player", binlogTemplate, func() interface{} { return agent.BinlogPlayerMap.Status() }) if onStatusRegistered != nil { onStatusRegistered() } }) }
func init() { servenv.OnRun(func() { if *disableActiveReparents { return } addCommand("Tablets", command{ "DemoteMaster", commandDemoteMaster, "<tablet alias>", "Demotes a master tablet."}) addCommand("Tablets", command{ "ReparentTablet", commandReparentTablet, "<tablet alias>", "Reparent a tablet to the current master in the shard. This only works if the current slave position matches the last known reparent action."}) addCommand("Shards", command{ "InitShardMaster", commandInitShardMaster, "[-force] [-wait_slave_timeout=<duration>] <keyspace/shard> <tablet alias>", "Sets the initial master for a shard. Will make all other tablets in the shard slaves of the provided master. WARNING: this could cause data loss on an already replicating shard. PlannedReparentShard or EmergencyReparentShard should be used instead."}) addCommand("Shards", command{ "PlannedReparentShard", commandPlannedReparentShard, "-keyspace_shard=<keyspace/shard> [-new_master=<tablet alias>] [-avoid_master=<tablet alias>]", "Reparents the shard to the new master, or away from old master. Both old and new master need to be up and running."}) addCommand("Shards", command{ "EmergencyReparentShard", commandEmergencyReparentShard, "-keyspace_shard=<keyspace/shard> -new_master=<tablet alias>", "Reparents the shard to the new master. Assumes the old master is dead and not responsding."}) }) }
func init() { servenv.OnRun(func() { if servenv.GRPCCheckServiceMap("vtctl") { grpcvtctlserver.StartServer(servenv.GRPCServer, ts) } }) }
func main() { defer exit.Recover() flag.Parse() servenv.Init() if initFakeZK != nil { initFakeZK() } ts := topo.GetServer() defer topo.CloseServers() resilientSrvTopoServer = vtgate.NewResilientSrvTopoServer(ts, "ResilientSrvTopoServer") healthCheck = discovery.NewHealthCheck(*connTimeoutTotal, *healthCheckRetryDelay, *healthCheckTimeout, "" /* statsSuffix */) tabletTypes := make([]topodatapb.TabletType, 0, 1) if len(*tabletTypesToWait) != 0 { for _, ttStr := range strings.Split(*tabletTypesToWait, ",") { tt, err := topoproto.ParseTabletType(ttStr) if err != nil { log.Errorf("unknown tablet type: %v", ttStr) continue } tabletTypes = append(tabletTypes, tt) } } vtg := vtgate.Init(context.Background(), healthCheck, ts, resilientSrvTopoServer, *cell, *retryDelay, *retryCount, *connTimeoutTotal, *connTimeoutPerConn, *connLife, tabletTypes, *maxInFlight, *testGateway) servenv.OnRun(func() { addStatusParts(vtg) }) servenv.RunDefault() }
func main() { defer exit.Recover() flag.Parse() servenv.Init() ts := topo.GetServer() defer topo.CloseServers() resilientSrvTopoServer = vtgate.NewResilientSrvTopoServer(ts, "ResilientSrvTopoServer") healthCheck = discovery.NewHealthCheck(*healthCheckConnTimeout, *healthCheckRetryDelay, *healthCheckTimeout) healthCheck.RegisterStats() tabletTypes := make([]topodatapb.TabletType, 0, 1) if len(*tabletTypesToWait) != 0 { for _, ttStr := range strings.Split(*tabletTypesToWait, ",") { tt, err := topoproto.ParseTabletType(ttStr) if err != nil { log.Errorf("unknown tablet type: %v", ttStr) continue } tabletTypes = append(tabletTypes, tt) } } l2vtg := l2vtgate.Init(healthCheck, ts, resilientSrvTopoServer, *cell, *retryCount, tabletTypes) servenv.OnRun(func() { addStatusParts(l2vtg) }) servenv.RunDefault() }
func init() { // Wait until flags are parsed, so we can check which topo server is in use. servenv.OnRun(func() { if etcdServer, ok := topo.GetServer().Impl.(*etcdtopo.Server); ok { vtctld.HandleExplorer("etcd", etcdtopo.NewExplorer(etcdServer)) } }) }
func init() { servenv.ServiceMap["grpc-mysqlctl"] = true servenv.OnRun(func() { if servenv.GRPCCheckServiceMap("mysqlctl") { grpcmysqlctlserver.StartServer(servenv.GRPCServer, mysqld) } }) }
func init() { servenv.RegisterGRPCFlags() servenv.OnRun(func() { if servenv.GRPCCheckServiceMap("vtworker") { grpcvtworkerserver.StartServer(servenv.GRPCServer, wi) } }) }
func init() { // Wait until flags are parsed, so we can check which topo server is in use. servenv.OnRun(func() { if zkServer, ok := topo.GetServer().Impl.(*zktopo.Server); ok { HandleExplorer("zk", "/zk/", "zk.html", NewZkExplorer(zkServer.GetZConn())) } }) }
func init() { servenv.InitServiceMap("grpc", "mysqlctl") servenv.OnRun(func() { if servenv.GRPCCheckServiceMap("mysqlctl") { grpcmysqlctlserver.StartServer(servenv.GRPCServer, mysqld) } }) }
func main() { defer exit.Recover() flag.Parse() servenv.Init() if initFakeZK != nil { initFakeZK() } ts := topo.GetServer() defer topo.CloseServers() var schema *planbuilder.Schema if *schemaFile != "" { var err error if schema, err = planbuilder.LoadFile(*schemaFile); err != nil { log.Error(err) exit.Return(1) } log.Infof("v3 is enabled: loaded schema from file: %v", *schemaFile) } else { ctx := context.Background() schemaJSON, err := ts.GetVSchema(ctx) if err != nil { log.Warningf("Skipping v3 initialization: GetVSchema failed: %v", err) goto startServer } schema, err = planbuilder.NewSchema([]byte(schemaJSON)) if err != nil { log.Warningf("Skipping v3 initialization: GetVSchema failed: %v", err) goto startServer } log.Infof("v3 is enabled: loaded schema from topo") } startServer: resilientSrvTopoServer = vtgate.NewResilientSrvTopoServer(ts, "ResilientSrvTopoServer") healthCheck = discovery.NewHealthCheck(*connTimeoutTotal, *healthCheckRetryDelay, *healthCheckTimeout, "" /* statsSuffix */) tabletTypes := make([]topodatapb.TabletType, 0, 1) if len(*tabletTypesToWait) != 0 { for _, ttStr := range strings.Split(*tabletTypesToWait, ",") { tt, err := topoproto.ParseTabletType(ttStr) if err != nil { log.Errorf("unknown tablet type: %v", ttStr) continue } tabletTypes = append(tabletTypes, tt) } } vtg := vtgate.Init(healthCheck, ts, resilientSrvTopoServer, schema, *cell, *retryDelay, *retryCount, *connTimeoutTotal, *connTimeoutPerConn, *connLife, tabletTypes, *maxInFlight, *testGateway) servenv.OnRun(func() { addStatusParts(vtg) }) servenv.RunDefault() }
func init() { servenv.OnRun(func() { if !*enableQueries { return } addCommandGroup(queriesGroupName) // VtGate commands addCommand(queriesGroupName, command{ "VtGateExecute", commandVtGateExecute, "-server <vtgate> [-bind_variables <JSON map>] [-connect_timeout <connect timeout>] [-keyspace <default keyspace>] [-tablet_type <tablet type>] [-json] <sql>", "Executes the given SQL query with the provided bound variables against the vtgate server."}) addCommand(queriesGroupName, command{ "VtGateExecuteShards", commandVtGateExecuteShards, "-server <vtgate> -keyspace <keyspace> -shards <shard0>,<shard1>,... [-bind_variables <JSON map>] [-connect_timeout <connect timeout>] [-tablet_type <tablet type>] [-json] <sql>", "Executes the given SQL query with the provided bound variables against the vtgate server. It is routed to the provided shards."}) addCommand(queriesGroupName, command{ "VtGateExecuteKeyspaceIds", commandVtGateExecuteKeyspaceIds, "-server <vtgate> -keyspace <keyspace> -keyspace_ids <ks1 in hex>,<k2 in hex>,... [-bind_variables <JSON map>] [-connect_timeout <connect timeout>] [-tablet_type <tablet type>] [-json] <sql>", "Executes the given SQL query with the provided bound variables against the vtgate server. It is routed to the shards that contain the provided keyspace ids."}) addCommand(queriesGroupName, command{ "VtGateSplitQuery", commandVtGateSplitQuery, "-server <vtgate> -keyspace <keyspace> [-split_column <split_column>] -split_count <split_count> [-bind_variables <JSON map>] [-connect_timeout <connect timeout>] <sql>", "Executes the SplitQuery computation for the given SQL query with the provided bound variables against the vtgate server (this is the base query for Map-Reduce workloads, and is provided here for debug / test purposes)."}) // VtTablet commands addCommand(queriesGroupName, command{ "VtTabletExecute", commandVtTabletExecute, "[-bind_variables <JSON map>] [-connect_timeout <connect timeout>] [-transaction_id <transaction_id>] [-tablet_type <tablet_type>] [-json] -keyspace <keyspace> -shard <shard> <tablet alias> <sql>", "Executes the given query on the given tablet."}) addCommand(queriesGroupName, command{ "VtTabletBegin", commandVtTabletBegin, "[-connect_timeout <connect timeout>] [-tablet_type <tablet_type>] -keyspace <keyspace> -shard <shard> <tablet alias>", "Starts a transaction on the provided server."}) addCommand(queriesGroupName, command{ "VtTabletCommit", commandVtTabletCommit, "[-connect_timeout <connect timeout>] [-tablet_type <tablet_type>] -keyspace <keyspace> -shard <shard> <tablet alias> <transaction_id>", "Commits a transaction on the provided server."}) addCommand(queriesGroupName, command{ "VtTabletRollback", commandVtTabletRollback, "[-connect_timeout <connect timeout>] [-tablet_type <tablet_type>] -keyspace <keyspace> -shard <shard> <tablet alias> <transaction_id>", "Rollbacks a transaction on the provided server."}) addCommand(queriesGroupName, command{ "VtTabletStreamHealth", commandVtTabletStreamHealth, "[-count <count, default 1>] [-connect_timeout <connect timeout>] <tablet alias>", "Executes the StreamHealth streaming query to a vttablet process. Will stop after getting <count> answers."}) }) }
func init() { servenv.OnRun(func() { if agent.IsRunningHealthCheck() { servenv.AddStatusFuncs(template.FuncMap{ "github_com_youtube_vitess_health_html_name": healthHTMLName, }) servenv.AddStatusPart("Health", healthTemplate, func() interface{} { return &healthStatus{Records: agent.History.Records()} }) } tabletserver.AddStatusPart() }) }
func init() { servenv.OnRun(func() { servenv.AddStatusPart("Topology Cache", topoTemplate, func() interface{} { return resilientSrvTopoServer.CacheStatus() }) servenv.AddStatusPart("Stats", statsTemplate, func() interface{} { return nil }) if onStatusRegistered != nil { onStatusRegistered() } }) }
func init() { servenv.OnRun(func() { http.Handle("/healthz", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { if _, err := agent.Healthy(); err != nil { http.Error(rw, fmt.Sprintf("500 internal server error: agent not healthy: %v", err), http.StatusInternalServerError) return } rw.Header().Set("Content-Length", fmt.Sprintf("%v", len(okMessage))) rw.WriteHeader(http.StatusOK) rw.Write(okMessage) })) }) }
// Init initializes VTGate server. func Init(ctx context.Context, hc discovery.HealthCheck, topoServer topo.Server, serv topo.SrvTopoServer, cell string, retryCount int, tabletTypesToWait []topodatapb.TabletType) *VTGate { if rpcVTGate != nil { log.Fatalf("VTGate already initialized") } rpcVTGate = &VTGate{ resolver: NewResolver(hc, topoServer, serv, "VttabletCall", cell, retryCount, tabletTypesToWait), timings: stats.NewMultiTimings("VtgateApi", []string{"Operation", "Keyspace", "DbType"}), rowsReturned: stats.NewMultiCounters("VtgateApiRowsReturned", []string{"Operation", "Keyspace", "DbType"}), logExecute: logutil.NewThrottledLogger("Execute", 5*time.Second), logExecuteShards: logutil.NewThrottledLogger("ExecuteShards", 5*time.Second), logExecuteKeyspaceIds: logutil.NewThrottledLogger("ExecuteKeyspaceIds", 5*time.Second), logExecuteKeyRanges: logutil.NewThrottledLogger("ExecuteKeyRanges", 5*time.Second), logExecuteEntityIds: logutil.NewThrottledLogger("ExecuteEntityIds", 5*time.Second), logExecuteBatchShards: logutil.NewThrottledLogger("ExecuteBatchShards", 5*time.Second), logExecuteBatchKeyspaceIds: logutil.NewThrottledLogger("ExecuteBatchKeyspaceIds", 5*time.Second), logStreamExecute: logutil.NewThrottledLogger("StreamExecute", 5*time.Second), logStreamExecuteKeyspaceIds: logutil.NewThrottledLogger("StreamExecuteKeyspaceIds", 5*time.Second), logStreamExecuteKeyRanges: logutil.NewThrottledLogger("StreamExecuteKeyRanges", 5*time.Second), logStreamExecuteShards: logutil.NewThrottledLogger("StreamExecuteShards", 5*time.Second), logUpdateStream: logutil.NewThrottledLogger("UpdateStream", 5*time.Second), } // vschemaCounters needs to be initialized before planner to // catch the initial load stats. vschemaCounters = stats.NewCounters("VtgateVSchemaCounts") // Resuse resolver's scatterConn. rpcVTGate.router = NewRouter(ctx, serv, cell, "VTGateRouter", rpcVTGate.resolver.scatterConn) normalErrors = stats.NewMultiCounters("VtgateApiErrorCounts", []string{"Operation", "Keyspace", "DbType"}) infoErrors = stats.NewCounters("VtgateInfoErrorCounts") internalErrors = stats.NewCounters("VtgateInternalErrorCounts") qpsByOperation = stats.NewRates("QPSByOperation", stats.CounterForDimension(rpcVTGate.timings, "Operation"), 15, 1*time.Minute) qpsByKeyspace = stats.NewRates("QPSByKeyspace", stats.CounterForDimension(rpcVTGate.timings, "Keyspace"), 15, 1*time.Minute) qpsByDbType = stats.NewRates("QPSByDbType", stats.CounterForDimension(rpcVTGate.timings, "DbType"), 15, 1*time.Minute) errorsByOperation = stats.NewRates("ErrorsByOperation", stats.CounterForDimension(normalErrors, "Operation"), 15, 1*time.Minute) errorsByKeyspace = stats.NewRates("ErrorsByKeyspace", stats.CounterForDimension(normalErrors, "Keyspace"), 15, 1*time.Minute) errorsByDbType = stats.NewRates("ErrorsByDbType", stats.CounterForDimension(normalErrors, "DbType"), 15, 1*time.Minute) servenv.OnRun(func() { for _, f := range RegisterVTGates { f(rpcVTGate) } }) vtgateOnce.Do(rpcVTGate.registerDebugHealthHandler) return rpcVTGate }
func main() { defer exit.Recover() flag.Parse() servenv.Init() // The implementation chain. servenv.OnRun(func() { s := services.CreateServices() for _, f := range vtgate.RegisterVTGates { f(s) } }) servenv.RunDefault() }
func init() { servenv.OnRun(func() { servenv.AddStatusPart("Topology Cache", topoTemplate, func() interface{} { return resilientSrvTopoServer.CacheStatus() }) servenv.AddStatusPart("Health Check Cache (NOT FOR QUERY ROUTING)", healthCheckTemplate, func() interface{} { return healthCheck.CacheStatus() }) servenv.AddStatusPart("Stats", statsTemplate, func() interface{} { return nil }) if onStatusRegistered != nil { onStatusRegistered() } }) }
// Init creates the single L2VTGate with the provided parameters. func Init(hc discovery.HealthCheck, topoServer topo.Server, serv topo.SrvTopoServer, cell string, retryCount int, tabletTypesToWait []topodatapb.TabletType) *L2VTGate { if l2VTGate != nil { log.Fatalf("L2VTGate already initialized") } gateway := gateway.GetCreator()(hc, topoServer, serv, cell, retryCount, tabletTypesToWait) l2VTGate = &L2VTGate{ gateway: gateway, } servenv.OnRun(func() { for _, f := range RegisterL2VTGates { f(l2VTGate) } }) return l2VTGate }
// init attempts to create a singleton InfluxDBBackend and register it as a PushBackend. // If it fails to create one, this is a noop. func init() { // Needs to happen in servenv.OnRun() instead of init because it requires flag parsing and logging servenv.OnRun(func() { config := &influxClient.ClientConfig{ Host: *influxDBHost, Username: *influxDBUsername, Password: *influxDBPassword, Database: *influxDBDatabase, } client, err := influxClient.NewClient(config) if err != nil { log.Errorf("Unable to create an InfluxDB client: %v", err) return } stats.RegisterPushBackend("influxdb", &InfluxDBBackend{ client: client, }) }) }
func init() { servenv.OnRun(func() { if WorkflowManager == nil { return } addCommandGroup(workflowsGroupName) addCommand(workflowsGroupName, command{ "WorkflowCreate", commandWorkflowCreate, "[-skip_start] <factoryName> [parameters...]", "Creates the workflow with the provided parameters. The workflow is also started, unless -skip_start is specified."}) addCommand(workflowsGroupName, command{ "WorkflowStart", commandWorkflowStart, "<uuid>", "Starts the workflow."}) addCommand(workflowsGroupName, command{ "WorkflowStop", commandWorkflowStop, "<uuid>", "Stops the workflow."}) addCommand(workflowsGroupName, command{ "WorkflowWait", commandWorkflowWait, "<uuid>", "Waits for the workflow to finish."}) addCommand(workflowsGroupName, command{ "WorkflowTree", commandWorkflowTree, "", "Displays a JSON representation of the workflow tree."}) addCommand(workflowsGroupName, command{ "WorkflowAction", commandWorkflowAction, "<path> <name>", "Sends the provided action name on the specified path."}) }) }
// Init creates the single L2VTGate with the provided parameters. func Init(hc discovery.HealthCheck, topoServer topo.Server, serv topo.SrvTopoServer, statsName, cell string, retryCount int, tabletTypesToWait []topodatapb.TabletType) *L2VTGate { if l2VTGate != nil { log.Fatalf("L2VTGate already initialized") } tabletCallErrorCountStatsName := "" if statsName != "" { tabletCallErrorCountStatsName = statsName + "ErrorCount" } gw := gateway.GetCreator()(hc, topoServer, serv, cell, retryCount) gateway.WaitForTablets(gw, tabletTypesToWait) l2VTGate = &L2VTGate{ timings: stats.NewMultiTimings(statsName, []string{"Operation", "Keyspace", "ShardName", "DbType"}), tabletCallErrorCount: stats.NewMultiCounters(tabletCallErrorCountStatsName, []string{"Operation", "Keyspace", "ShardName", "DbType"}), gateway: gw, } servenv.OnRun(func() { for _, f := range RegisterL2VTGates { f(l2VTGate) } }) return l2VTGate }
func main() { defer exit.Recover() flags := dbconfigs.AppConfig | dbconfigs.AllPrivsConfig | 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) } // creates and registers the query service qsc := tabletserver.NewServer() servenv.OnRun(func() { qsc.Register() addStatusParts(qsc) }) servenv.OnClose(func() { // We now leave the queryservice running during lameduck, // so stop it in OnClose(), after lameduck is over. qsc.StopService() }) if *tableAclConfig != "" { // To override default simpleacl, other ACL plugins must set themselves to be default ACL factory tableacl.Register("simpleacl", &simpleacl.Factory{}) } 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) } // tabletacl.Init loads ACL from file if *tableAclConfig is not empty err = tableacl.Init( *tableAclConfig, func() { qsc.ClearQueryPlanCache() }, ) if err != nil { log.Errorf("Fail to initialize Table ACL: %v", err) if *enforceTableACLConfig { log.Error("Need a valid initial Table ACL when enforce-tableacl-config is set, exiting.") 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(mycnf, &dbcfgs.Dba, &dbcfgs.AllPrivs, &dbcfgs.App, &dbcfgs.Repl, true /* enablePublishStats */) servenv.OnClose(mysqld.Close) // 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) if err != nil { log.Error(err) exit.Return(1) } 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 }
// 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 }
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 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() }