func main() { flag.Parse() servenv.Init() defer servenv.Close() unmarshalFile(*dbConfigFile, &dbconfig) log.Infof("dbconfig: %s\n", dbconfig) unmarshalFile(*overridesFile, &schemaOverrides) data, _ := json.MarshalIndent(schemaOverrides, "", " ") log.Infof("schemaOverrides: %s\n", data) ts.InitQueryService() ts.AllowQueries(dbconfig, schemaOverrides, ts.LoadCustomRules()) servenv.ServeRPC() log.Infof("starting vtocc %v", *port) s := proc.ListenAndServe(fmt.Sprintf("%v", *port)) // A SIGUSR1 means that we're restarting if s == syscall.SIGUSR1 { // Give some time for the other process // to pick up the listeners time.Sleep(5 * time.Millisecond) ts.DisallowQueries(true) } else { ts.DisallowQueries(false) } }
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.OnClose(func() { time.Sleep(5 * time.Millisecond) ts.DisallowQueries() }) servenv.Run() }
func main() { defaultDBConfig := dbconfigs.DefaultDBConfigs.App defaultDBConfig.Host = "localhost" dbconfigs.RegisterAppFlags(defaultDBConfig) flag.Parse() servenv.Init() dbConfig, err := dbconfigs.InitApp("") if err != nil { log.Fatalf("Cannot initialize App dbconfig: %v", err) } unmarshalFile(*overridesFile, &schemaOverrides) data, _ := json.MarshalIndent(schemaOverrides, "", " ") log.Infof("schemaOverrides: %s\n", data) ts.InitQueryService() ts.AllowQueries(dbConfig, schemaOverrides, ts.LoadCustomRules()) log.Infof("starting vtocc %v", *port) servenv.OnClose(func() { time.Sleep(5 * time.Millisecond) ts.DisallowQueries() }) servenv.Run(*port) }
func (agent *ActionAgent) disallowQueries() { if agent.DBConfigs == nil { // test instance, do nothing return } tabletserver.DisallowQueries() }
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.OnClose(func() { time.Sleep(5 * time.Millisecond) 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 main() { dbConfigsFile, dbCredentialsFile := dbconfigs.RegisterCommonFlags() flag.Parse() servenv.Init() 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, *dbConfigsFile, *dbCredentialsFile) if err != nil { log.Warning(err) } ts.InitQueryService() mysqlctl.RegisterUpdateStreamService(mycnf) // Depends on both query and updateStream. ts.RegisterCacheInvalidator() // Depends on both query and updateStream. if err := vttablet.InitAgent(tabletAlias, dbcfgs, mycnf, *dbConfigsFile, *dbCredentialsFile, *port, *securePort, *mycnfFile, *overridesFile); err != nil { log.Fatal(err) } vttablet.HttpHandleSnapshots(mycnf, tabletAlias.Uid) servenv.OnClose(func() { time.Sleep(5 * time.Millisecond) ts.DisallowQueries() mysqlctl.DisableUpdateStreamService() topo.CloseServers() vttablet.CloseAgent() }) servenv.RunSecure(*port, *securePort, *cert, *key, *caCert) }
func main() { dbCredentialsFile := dbconfigs.RegisterAppFlags(DefaultDBConfig) flag.Parse() servenv.Init() dbConfigs, _ := dbconfigs.Init("", *dbCredentialsFile) unmarshalFile(*overridesFile, &schemaOverrides) data, _ := json.MarshalIndent(schemaOverrides, "", " ") log.Infof("schemaOverrides: %s\n", data) ts.InitQueryService() ts.AllowQueries(dbConfigs.App, schemaOverrides, ts.LoadCustomRules()) log.Infof("starting vtocc %v", *port) servenv.OnClose(func() { time.Sleep(5 * time.Millisecond) ts.DisallowQueries() }) servenv.Run(*port) }
func initQueryService(dbcfgs dbconfigs.DBConfigs) { ts.SqlQueryLogger.ServeLogs("/debug/querylog") ts.TxLogger.ServeLogs("/debug/txlog") if err := jscfg.ReadJson(*qsConfigFile, &qsConfig); err != nil { relog.Warning("%s", err) } ts.RegisterQueryService(qsConfig) usefulLameDuckPeriod := float64(qsConfig.QueryTimeout + 1) if usefulLameDuckPeriod > *lameDuckPeriod { *lameDuckPeriod = usefulLameDuckPeriod relog.Info("readjusted -lame-duck-period to %f", *lameDuckPeriod) } if *queryLog != "" { if f, err := os.OpenFile(*queryLog, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644); err == nil { ts.QueryLogger = relog.New(f, "", relog.DEBUG) } else { relog.Fatal("Error opening file %v: %v", *queryLog, err) } } umgmt.AddCloseCallback(func() { ts.DisallowQueries(true) }) }
// InitAgent initializes the agent within vttablet. func InitAgent( tabletAlias topo.TabletAlias, dbcfgs *dbconfigs.DBConfigs, mycnf *mysqlctl.Mycnf, port, securePort int, overridesFile string, ) (agent *tabletmanager.ActionAgent, err error) { schemaOverrides := loadSchemaOverrides(overridesFile) topoServer := topo.GetServer() mysqld := mysqlctl.NewMysqld(mycnf, &dbcfgs.Dba, &dbcfgs.Repl) statsType := stats.NewString("TabletType") statsKeyspace := stats.NewString("TabletKeyspace") statsShard := stats.NewString("TabletShard") statsKeyRangeStart := stats.NewString("TabletKeyRangeStart") statsKeyRangeEnd := stats.NewString("TabletKeyRangeEnd") agent, err = tabletmanager.NewActionAgent(topoServer, tabletAlias, mysqld) if err != nil { return nil, err } // Start the binlog player services, not playing at start. agent.BinlogPlayerMap = tabletmanager.NewBinlogPlayerMap(topoServer, &dbcfgs.App.ConnectionParams, mysqld) tabletmanager.RegisterBinlogPlayerMap(agent.BinlogPlayerMap) // Action agent listens to changes in zookeeper and makes // modifications to this tablet. agent.AddChangeCallback(func(oldTablet, newTablet topo.Tablet) { allowQuery := true var shardInfo *topo.ShardInfo var keyspaceInfo *topo.KeyspaceInfo if newTablet.Type == topo.TYPE_MASTER { // read the shard to get SourceShards shardInfo, err = topoServer.GetShard(newTablet.Keyspace, newTablet.Shard) if err != nil { log.Errorf("Cannot read shard for this tablet %v: %v", newTablet.Alias, err) } else { allowQuery = len(shardInfo.SourceShards) == 0 } // read the keyspace to get ShardingColumnType keyspaceInfo, err = topoServer.GetKeyspace(newTablet.Keyspace) switch err { case nil: // continue case topo.ErrNoNode: // backward compatible mode keyspaceInfo = topo.NewKeyspaceInfo(newTablet.Keyspace, &topo.Keyspace{}) default: log.Errorf("Cannot read keyspace for this tablet %v: %v", newTablet.Alias, err) keyspaceInfo = nil } } if newTablet.IsRunningQueryService() && allowQuery { if dbcfgs.App.DbName == "" { dbcfgs.App.DbName = newTablet.DbName() } dbcfgs.App.Keyspace = newTablet.Keyspace dbcfgs.App.Shard = newTablet.Shard if newTablet.Type != topo.TYPE_MASTER { dbcfgs.App.EnableInvalidator = true } else { dbcfgs.App.EnableInvalidator = false } // Transitioning from replica to master, first disconnect // existing connections. "false" indicateds that clients must // re-resolve their endpoint before reconnecting. if newTablet.Type == topo.TYPE_MASTER && oldTablet.Type != topo.TYPE_MASTER { ts.DisallowQueries() } qrs := ts.LoadCustomRules() if newTablet.KeyRange.IsPartial() { qr := ts.NewQueryRule("enforce keyspace_id range", "keyspace_id_not_in_range", ts.QR_FAIL_QUERY) qr.AddPlanCond(sqlparser.PLAN_INSERT_PK) err = qr.AddBindVarCond("keyspace_id", true, true, ts.QR_NOTIN, newTablet.KeyRange) if err != nil { log.Warningf("Unable to add keyspace rule: %v", err) } else { qrs.Add(qr) } } ts.AllowQueries(&dbcfgs.App, schemaOverrides, qrs, mysqld) // Disable before enabling to force existing streams to stop. binlog.DisableUpdateStreamService() binlog.EnableUpdateStreamService(dbcfgs) } else { ts.DisallowQueries() binlog.DisableUpdateStreamService() } statsType.Set(string(newTablet.Type)) statsKeyspace.Set(newTablet.Keyspace) statsShard.Set(newTablet.Shard) statsKeyRangeStart.Set(string(newTablet.KeyRange.Start.Hex())) statsKeyRangeEnd.Set(string(newTablet.KeyRange.End.Hex())) // See if we need to start or stop any binlog player if newTablet.Type == topo.TYPE_MASTER { agent.BinlogPlayerMap.RefreshMap(newTablet, keyspaceInfo, shardInfo) } else { agent.BinlogPlayerMap.StopAllPlayersAndReset() } }) if err := agent.Start(mysqld.Port(), port, securePort); err != nil { return nil, err } // register the RPC services from the agent agent.RegisterQueryService() return agent, nil }
func (agent *ActionAgent) disallowQueries() { tabletserver.DisallowQueries() }
func main() { flag.Parse() if err := servenv.Init("vtocc"); err != nil { relog.Fatal("Error in servenv.Init: %v", err) } if *queryLog != "" { if f, err := os.OpenFile(*queryLog, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644); err == nil { ts.QueryLogger = relog.New(f, "", relog.DEBUG) } else { relog.Fatal("Error opening file %v: %v", *queryLog, err) } } ts.SqlQueryLogger.ServeLogs("/debug/querylog") ts.TxLogger.ServeLogs("/debug/txlog") unmarshalFile(*configFile, &config) data, _ := json.MarshalIndent(config, "", " ") relog.Info("config: %s\n", data) unmarshalFile(*dbConfigFile, &dbconfig) relog.Info("dbconfig: %s\n", dbconfig) unmarshalFile(*overridesFile, &schemaOverrides) data, _ = json.MarshalIndent(schemaOverrides, "", " ") relog.Info("schemaOverrides: %s\n", data) ts.RegisterQueryService(config) qrs := loadCustomRules() ts.AllowQueries(dbconfig, schemaOverrides, qrs) rpc.HandleHTTP() // NOTE(szopa): Changing credentials requires a server // restart. if *authConfig != "" { if err := auth.LoadCredentials(*authConfig); err != nil { relog.Error("could not load authentication credentials, not starting rpc servers: %v", err) } serveAuthRPC() } serveRPC() relog.Info("started vtocc %v", *port) // we delegate out startup to the micromanagement server so these actions // will occur after we have obtained our socket. usefulLameDuckPeriod := float64(config.QueryTimeout + 1) if usefulLameDuckPeriod > *lameDuckPeriod { *lameDuckPeriod = usefulLameDuckPeriod relog.Info("readjusted -lame-duck-period to %f", *lameDuckPeriod) } umgmt.SetLameDuckPeriod(float32(*lameDuckPeriod)) umgmt.SetRebindDelay(float32(*rebindDelay)) umgmt.AddStartupCallback(func() { umgmt.StartHttpServer(fmt.Sprintf(":%v", *port)) }) umgmt.AddStartupCallback(func() { c := make(chan os.Signal, 1) signal.Notify(c, syscall.SIGTERM) go func() { for sig := range c { umgmt.SigTermHandler(sig) } }() }) umgmt.AddCloseCallback(func() { ts.DisallowQueries(true) }) umgmtSocket := fmt.Sprintf("/tmp/vtocc-%08x-umgmt.sock", *port) if umgmtErr := umgmt.ListenAndServe(umgmtSocket); umgmtErr != nil { relog.Error("umgmt.ListenAndServe err: %v", umgmtErr) } relog.Info("done") }
func initAgent(tabletAlias topo.TabletAlias, dbcfgs dbconfigs.DBConfigs, mycnf *mysqlctl.Mycnf, dbConfigsFile, dbCredentialsFile string) error { topoServer := topo.GetServer() umgmt.AddCloseCallback(func() { topo.CloseServers() }) bindAddr := fmt.Sprintf(":%v", *port) secureAddr := "" if *securePort != 0 { secureAddr = fmt.Sprintf(":%v", *securePort) } // Action agent listens to changes in zookeeper and makes // modifications to this tablet. agent, err := tm.NewActionAgent(topoServer, tabletAlias, *mycnfFile, dbConfigsFile, dbCredentialsFile) if err != nil { return err } agent.AddChangeCallback(func(oldTablet, newTablet topo.Tablet) { if newTablet.IsServingType() { if dbcfgs.App.Dbname == "" { dbcfgs.App.Dbname = newTablet.DbName() } dbcfgs.App.KeyRange = newTablet.KeyRange dbcfgs.App.Keyspace = newTablet.Keyspace dbcfgs.App.Shard = newTablet.Shard // Transitioning from replica to master, first disconnect // existing connections. "false" indicateds that clients must // re-resolve their endpoint before reconnecting. if newTablet.Type == topo.TYPE_MASTER && oldTablet.Type != topo.TYPE_MASTER { ts.DisallowQueries(false) } qrs := loadCustomRules() if dbcfgs.App.KeyRange.IsPartial() { qr := ts.NewQueryRule("enforce keyspace_id range", "keyspace_id_not_in_range", ts.QR_FAIL_QUERY) qr.AddPlanCond(sqlparser.PLAN_INSERT_PK) err = qr.AddBindVarCond("keyspace_id", true, true, ts.QR_NOTIN, dbcfgs.App.KeyRange) if err != nil { relog.Warning("Unable to add keyspace rule: %v", err) } else { qrs.Add(qr) } } ts.AllowQueries(dbcfgs.App, schemaOverrides, qrs) mysqlctl.EnableUpdateStreamService(string(newTablet.Type), dbcfgs) if newTablet.Type != topo.TYPE_MASTER { ts.StartRowCacheInvalidation() } } else { ts.DisallowQueries(false) mysqlctl.DisableUpdateStreamService() if newTablet.Type != topo.TYPE_MASTER { ts.StopRowCacheInvalidation() } } }) mysqld := mysqlctl.NewMysqld(mycnf, dbcfgs.Dba, dbcfgs.Repl) if err := agent.Start(bindAddr, secureAddr, mysqld.Addr()); err != nil { return err } umgmt.AddCloseCallback(func() { agent.Stop() }) // register the RPC services from the agent agent.RegisterQueryService(mysqld) return nil }
// InitAgent initializes the agent within vttablet. func InitAgent( tabletAlias topo.TabletAlias, dbcfgs dbconfigs.DBConfigs, mycnf *mysqlctl.Mycnf, dbConfigsFile, dbCredentialsFile string, port, securePort int, mycnfFile, overridesFile string) (err error) { schemaOverrides := loadSchemaOverrides(overridesFile) topoServer := topo.GetServer() // Start the binlog server service, disabled at start. binlogServer = mysqlctl.NewBinlogServer(mycnf) mysqlctl.RegisterBinlogServerService(binlogServer) // Start the binlog player services, not playing at start. binlogPlayerMap = NewBinlogPlayerMap(topoServer, &dbcfgs.Dba) RegisterBinlogPlayerMap(binlogPlayerMap) // Compute the bind addresses bindAddr := fmt.Sprintf(":%v", port) secureAddr := "" if securePort != 0 { secureAddr = fmt.Sprintf(":%v", securePort) } exportedType := expvar.NewString("tablet-type") // Action agent listens to changes in zookeeper and makes // modifications to this tablet. agent, err = tm.NewActionAgent(topoServer, tabletAlias, mycnfFile, dbConfigsFile, dbCredentialsFile) if err != nil { return err } agent.AddChangeCallback(func(oldTablet, newTablet topo.Tablet) { if newTablet.IsServingType() { if dbcfgs.App.Dbname == "" { dbcfgs.App.Dbname = newTablet.DbName() } dbcfgs.App.KeyRange = newTablet.KeyRange dbcfgs.App.Keyspace = newTablet.Keyspace dbcfgs.App.Shard = newTablet.Shard // Transitioning from replica to master, first disconnect // existing connections. "false" indicateds that clients must // re-resolve their endpoint before reconnecting. if newTablet.Type == topo.TYPE_MASTER && oldTablet.Type != topo.TYPE_MASTER { ts.DisallowQueries(false) } qrs := ts.LoadCustomRules() if dbcfgs.App.KeyRange.IsPartial() { qr := ts.NewQueryRule("enforce keyspace_id range", "keyspace_id_not_in_range", ts.QR_FAIL_QUERY) qr.AddPlanCond(sqlparser.PLAN_INSERT_PK) err = qr.AddBindVarCond("keyspace_id", true, true, ts.QR_NOTIN, dbcfgs.App.KeyRange) if err != nil { log.Warningf("Unable to add keyspace rule: %v", err) } else { qrs.Add(qr) } } ts.AllowQueries(dbcfgs.App, schemaOverrides, qrs) mysqlctl.EnableUpdateStreamService(string(newTablet.Type), dbcfgs) if newTablet.Type != topo.TYPE_MASTER { ts.StartRowCacheInvalidation() } } else { ts.DisallowQueries(false) ts.StopRowCacheInvalidation() mysqlctl.DisableUpdateStreamService() } exportedType.Set(string(newTablet.Type)) // BinlogServer is only enabled for replicas if newTablet.Type == topo.TYPE_REPLICA { if !mysqlctl.IsBinlogServerEnabled(binlogServer) { mysqlctl.EnableBinlogServerService(binlogServer, dbcfgs.App.Dbname) } } else { if mysqlctl.IsBinlogServerEnabled(binlogServer) { mysqlctl.DisableBinlogServerService(binlogServer) } } // See if we need to start or stop any binlog player if newTablet.Type == topo.TYPE_MASTER { binlogPlayerMap.RefreshMap(newTablet) } else { binlogPlayerMap.StopAllPlayers() } }) mysqld := mysqlctl.NewMysqld(mycnf, dbcfgs.Dba, dbcfgs.Repl) if err := agent.Start(bindAddr, secureAddr, mysqld.Addr()); err != nil { return err } // register the RPC services from the agent agent.RegisterQueryService(mysqld) return nil }
func main() { dbConfigsFile, dbCredentialsFile := dbconfigs.RegisterCommonFlags() flag.Parse() servenv.Init() defer servenv.Close() 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, *dbConfigsFile, *dbCredentialsFile) if err != nil { log.Warning(err) } ts.InitQueryService() mysqlctl.RegisterUpdateStreamService(mycnf) // Depends on both query and updateStream. ts.RegisterCacheInvalidator() // Depends on both query and updateStream. if err := vttablet.InitAgent(tabletAlias, dbcfgs, mycnf, *dbConfigsFile, *dbCredentialsFile, *port, *securePort, *mycnfFile, *overridesFile); err != nil { log.Fatal(err) } servenv.ServeRPC() vttablet.HttpHandleSnapshots(mycnf, tabletAlias.Uid) l, err := proc.Listen(fmt.Sprintf("%v", *port)) if err != nil { log.Fatal(err) } go http.Serve(l, nil) if *securePort != 0 { log.Infof("listening on secure port %v", *securePort) vttablet.SecureServe(fmt.Sprintf(":%d", *securePort), *cert, *key, *caCert) } log.Infof("started vttablet %v", *port) s := proc.Wait() // A SIGUSR1 means that we're restarting if s == syscall.SIGUSR1 { // Give some time for the other process // to pick up the listeners log.Info("Exiting on SIGUSR1") time.Sleep(5 * time.Millisecond) ts.DisallowQueries(true) } else { log.Info("Exiting on SIGTERM") ts.DisallowQueries(false) } mysqlctl.DisableUpdateStreamService() topo.CloseServers() vttablet.CloseAgent() }
// InitAgent initializes the agent within vttablet. func InitAgent( tabletAlias topo.TabletAlias, dbcfgs *dbconfigs.DBConfigs, mycnf *mysqlctl.Mycnf, port, securePort int, overridesFile string, ) (agent *tabletmanager.ActionAgent, err error) { schemaOverrides := loadSchemaOverrides(overridesFile) topoServer := topo.GetServer() mysqld := mysqlctl.NewMysqld(mycnf, &dbcfgs.Dba, &dbcfgs.Repl) statsType := stats.NewString("TabletType") statsKeyspace := stats.NewString("TabletKeyspace") statsShard := stats.NewString("TabletShard") statsKeyRangeStart := stats.NewString("TabletKeyRangeStart") statsKeyRangeEnd := stats.NewString("TabletKeyRangeEnd") agent, err = tabletmanager.NewActionAgent(topoServer, tabletAlias, mysqld) if err != nil { return nil, err } // Start the binlog player services, not playing at start. agent.BinlogPlayerMap = tabletmanager.NewBinlogPlayerMap(topoServer, &dbcfgs.App.ConnectionParams, mysqld) tabletmanager.RegisterBinlogPlayerMap(agent.BinlogPlayerMap) // Action agent listens to changes in zookeeper and makes // modifications to this tablet. agent.AddChangeCallback(func(oldTablet, newTablet topo.Tablet) { allowQuery := true var shardInfo *topo.ShardInfo var keyspaceInfo *topo.KeyspaceInfo if newTablet.Type == topo.TYPE_MASTER { // read the shard to get SourceShards shardInfo, err = topoServer.GetShard(newTablet.Keyspace, newTablet.Shard) if err != nil { log.Errorf("Cannot read shard for this tablet %v: %v", newTablet.Alias, err) } else { allowQuery = len(shardInfo.SourceShards) == 0 } // read the keyspace to get ShardingColumnType keyspaceInfo, err = topoServer.GetKeyspace(newTablet.Keyspace) switch err { case nil: // continue case topo.ErrNoNode: // backward compatible mode keyspaceInfo = topo.NewKeyspaceInfo(newTablet.Keyspace, &topo.Keyspace{}) default: log.Errorf("Cannot read keyspace for this tablet %v: %v", newTablet.Alias, err) keyspaceInfo = nil } } if newTablet.IsRunningQueryService() && allowQuery { if dbcfgs.App.DbName == "" { dbcfgs.App.DbName = newTablet.DbName() } dbcfgs.App.Keyspace = newTablet.Keyspace dbcfgs.App.Shard = newTablet.Shard if newTablet.Type != topo.TYPE_MASTER { dbcfgs.App.EnableInvalidator = true } else { dbcfgs.App.EnableInvalidator = false } // There are a few transitions when we're // going to need to restart the query service: // - transitioning from replica to master, so clients // that were already connected don't keep on using // the master as replica or rdonly. // - having different parameters for the query // service. It needs to stop and restart with the // new parameters. That includes: // - changing KeyRange // - changing the BlacklistedTables list if (newTablet.Type == topo.TYPE_MASTER && oldTablet.Type != topo.TYPE_MASTER) || (newTablet.KeyRange != oldTablet.KeyRange) || !reflect.DeepEqual(newTablet.BlacklistedTables, oldTablet.BlacklistedTables) { ts.DisallowQueries() } qrs := ts.LoadCustomRules() if newTablet.KeyRange.IsPartial() { qr := ts.NewQueryRule("enforce keyspace_id range", "keyspace_id_not_in_range", ts.QR_FAIL_QUERY) qr.AddPlanCond(sqlparser.PLAN_INSERT_PK) err = qr.AddBindVarCond("keyspace_id", true, true, ts.QR_NOTIN, newTablet.KeyRange) if err != nil { log.Warningf("Unable to add keyspace rule: %v", err) } else { qrs.Add(qr) } } if len(newTablet.BlacklistedTables) > 0 { log.Infof("Blacklisting tables %v", strings.Join(newTablet.BlacklistedTables, ", ")) qr := ts.NewQueryRule("enforce blacklisted tables", "blacklisted_table", ts.QR_FAIL_QUERY) for _, t := range newTablet.BlacklistedTables { qr.AddTableCond(t) } qrs.Add(qr) } ts.AllowQueries(&dbcfgs.App, schemaOverrides, qrs, mysqld) // Disable before enabling to force existing streams to stop. binlog.DisableUpdateStreamService() binlog.EnableUpdateStreamService(dbcfgs) } else { ts.DisallowQueries() binlog.DisableUpdateStreamService() } statsType.Set(string(newTablet.Type)) statsKeyspace.Set(newTablet.Keyspace) statsShard.Set(newTablet.Shard) statsKeyRangeStart.Set(string(newTablet.KeyRange.Start.Hex())) statsKeyRangeEnd.Set(string(newTablet.KeyRange.End.Hex())) // See if we need to start or stop any binlog player if newTablet.Type == topo.TYPE_MASTER { agent.BinlogPlayerMap.RefreshMap(newTablet, keyspaceInfo, shardInfo) } else { agent.BinlogPlayerMap.StopAllPlayersAndReset() } }) if err := agent.Start(mysqld.Port(), port, securePort); err != nil { return nil, err } // register the RPC services from the agent agent.RegisterQueryService() // start health check if needed initHeathCheck(agent) return agent, nil }