func main() { dbConfigsFile, dbCredentialsFile := dbconfigs.RegisterCommonFlags() flag.Parse() servenv.Init() if *mycnfFile == "" { log.Fatalf("Please specify the path for mycnf file.") } mycnf, err := mysqlctl.ReadMycnf(*mycnfFile) if err != nil { log.Fatalf("Error reading mycnf file %v", *mycnfFile) } dbcfgs, err := dbconfigs.Init(mycnf.SocketFile, *dbConfigsFile, *dbCredentialsFile) if err != nil { log.Warning(err) } mysqld := mysqlctl.NewMysqld(mycnf, dbcfgs.Dba, dbcfgs.Repl) binlogServer := mysqlctl.NewBinlogServer(mysqld) mysqlctl.EnableBinlogServerService(binlogServer, *dbname) proto.RegisterBinlogServer(binlogServer) rpcwrap.RegisterAuthenticated(binlogServer) servenv.OnClose(func() { mysqlctl.DisableBinlogServerService(binlogServer) }) servenv.Run(*port) }
// NewServer starts a new unregistered TabletServer. // You have to end it with StopService once testing is done. func NewServer(config tabletserver.Config, connParams sqldb.ConnParams, enableRowcache bool) (*tabletserver.TabletServer, error) { dbcfgs := dbconfigs.DBConfigs{ App: dbconfigs.DBConfig{ ConnParams: connParams, Keyspace: "vttest", Shard: "0", EnableRowcache: enableRowcache, EnableInvalidator: false, }, } mysqld := mysqlctl.NewMysqld( "Dba", "App", &mysqlctl.Mycnf{}, &dbcfgs.Dba, &dbcfgs.App.ConnParams, &dbcfgs.Repl) Target = query.Target{ Keyspace: "vttest", Shard: "0", TabletType: topodata.TabletType_MASTER, } server := tabletserver.NewTabletServer(config) err := server.StartService(&Target, &dbcfgs, nil, mysqld) if err != nil { return nil, err } return server, nil }
func main() { dbConfigsFile, dbCredentialsFile := dbconfigs.RegisterCommonFlags() flag.Parse() relog.Info("started vtaction %v", os.Args) rpc.HandleHTTP() jsonrpc.ServeHTTP() jsonrpc.ServeRPC() bsonrpc.ServeHTTP() bsonrpc.ServeRPC() logFile, err := os.OpenFile(*logFilename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0666) if err != nil { relog.Fatal("Can't open log file: %v", err) } relog.SetOutput(logFile) relog.SetPrefix(fmt.Sprintf("vtaction [%v] ", os.Getpid())) if err := relog.SetLevelByName(*logLevel); err != nil { relog.Fatal("%v", err) } relog.HijackLog(nil) relog.HijackStdio(logFile, logFile) mycnf, mycnfErr := mysqlctl.ReadMycnf(*mycnfFile) if mycnfErr != nil { relog.Fatal("mycnf read failed: %v", mycnfErr) } relog.Debug("mycnf: %v", jscfg.ToJson(mycnf)) dbcfgs, cfErr := dbconfigs.Init(mycnf.SocketFile, *dbConfigsFile, *dbCredentialsFile) if err != nil { relog.Fatal("%s", cfErr) } mysqld := mysqlctl.NewMysqld(mycnf, dbcfgs.Dba, dbcfgs.Repl) topoServer := topo.GetServer() defer topo.CloseServers() actor := tabletmanager.NewTabletActor(mysqld, topoServer) // we delegate out startup to the micromanagement server so these actions // will occur after we have obtained our socket. bindAddr := fmt.Sprintf(":%v", *port) httpServer := &http.Server{Addr: bindAddr} go func() { if err := httpServer.ListenAndServe(); err != nil { relog.Error("httpServer.ListenAndServe err: %v", err) } }() actionErr := actor.HandleAction(*actionNode, *action, *actionGuid, *force) if actionErr != nil { relog.Fatal("action error: %v", actionErr) } relog.Info("finished vtaction %v", os.Args) }
func (updateStream *UpdateStream) enable(dbcfgs *dbconfigs.DBConfigs) { updateStream.actionLock.Lock() defer updateStream.actionLock.Unlock() if updateStream.isEnabled() { return } if dbcfgs.Dba.UnixSocket == "" { log.Errorf("Missing dba socket connection, cannot enable update stream service") return } if dbcfgs.App.DbName == "" { log.Errorf("Missing db name, cannot enable update stream service") return } if updateStream.mycnf.BinLogPath == "" { log.Errorf("Update stream service requires binlogs enabled") return } updateStream.state.Set(ENABLED) updateStream.mysqld = mysqlctl.NewMysqld(updateStream.mycnf, &dbcfgs.Dba, &dbcfgs.Repl) updateStream.dbname = dbcfgs.App.DbName updateStream.streams.Init() log.Infof("Enabling update stream, dbname: %s, binlogpath: %s", updateStream.dbname, updateStream.mycnf.BinLogPath) }
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() { 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") } }
// StartDefaultServer starts the default server and initializes // all the global variables. This function should only be called // once at the beginning of the test. func StartDefaultServer(connParams sqldb.ConnParams, schemaOverrides []tabletserver.SchemaOverride) error { dbcfgs := dbconfigs.DBConfigs{ App: dbconfigs.DBConfig{ ConnParams: connParams, Keyspace: "vttest", Shard: "0", EnableRowcache: true, EnableInvalidator: false, }, } mysqld := mysqlctl.NewMysqld( "Dba", "App", &mysqlctl.Mycnf{}, &dbcfgs.Dba, &dbcfgs.App.ConnParams, &dbcfgs.Repl) BaseConfig = tabletserver.DefaultQsConfig BaseConfig.RowCache.Binary = vttest.MemcachedPath() BaseConfig.RowCache.Socket = path.Join(os.TempDir(), "memcache.sock") BaseConfig.RowCache.Connections = 100 BaseConfig.EnableAutoCommit = true BaseConfig.StrictTableAcl = true Target = query.Target{ Keyspace: "vttest", Shard: "0", TabletType: topodata.TabletType_MASTER, } DefaultServer = tabletserver.NewTabletServer(BaseConfig) DefaultServer.Register() err := DefaultServer.StartService(&Target, &dbcfgs, schemaOverrides, mysqld) if err != nil { return fmt.Errorf("could not start service: %v\n", err) } // Start http service. ln, err := net.Listen("tcp", ":0") if err != nil { return fmt.Errorf("could not start listener: %v\n", err) } ServerAddress = fmt.Sprintf("http://%s", ln.Addr().String()) go http.Serve(ln, nil) for { time.Sleep(10 * time.Millisecond) response, err := http.Get(fmt.Sprintf("%s/debug/vars", ServerAddress)) if err == nil { response.Body.Close() break } } return nil }
func (util *testUtils) newMysqld(dbconfigs *dbconfigs.DBConfigs) mysqlctl.MysqlDaemon { return mysqlctl.NewMysqld( "", "", mysqlctl.NewMycnf(0, 6802), &dbconfigs.Dba, &dbconfigs.App.ConnParams, &dbconfigs.Repl, ) }
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() }
// NewActionAgent creates a new ActionAgent and registers all the // associated services func NewActionAgent( tabletAlias topo.TabletAlias, dbcfgs *dbconfigs.DBConfigs, mycnf *mysqlctl.Mycnf, port, securePort int, overridesFile string, lockTimeout time.Duration, ) (agent *ActionAgent, err error) { schemaOverrides := loadSchemaOverrides(overridesFile) topoServer := topo.GetServer() mysqld := mysqlctl.NewMysqld("Dba", mycnf, &dbcfgs.Dba, &dbcfgs.Repl) agent = &ActionAgent{ TopoServer: topoServer, TabletAlias: tabletAlias, Mysqld: mysqld, MysqlDaemon: mysqld, DBConfigs: dbcfgs, SchemaOverrides: schemaOverrides, LockTimeout: lockTimeout, done: make(chan struct{}), History: history.New(historyLength), lastHealthMapCount: stats.NewInt("LastHealthMapCount"), changeItems: make(chan tabletChangeItem, 100), } // Start the binlog player services, not playing at start. agent.BinlogPlayerMap = NewBinlogPlayerMap(topoServer, &dbcfgs.Filtered, mysqld) 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) } } if err := agent.Start(mysqlPort, port, securePort); err != nil { return nil, err } // register the RPC services from the agent agent.registerQueryService() // start health check if needed agent.initHeathCheck() return agent, nil }
func main() { flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s [global parameters] command [command parameters]\n", os.Args[0]) fmt.Fprintf(os.Stderr, "\nThe global optional parameters are:\n") flag.PrintDefaults() fmt.Fprintf(os.Stderr, "\nThe commands are listed below. Use '%s <command> -h' for more help.\n\n", os.Args[0]) for _, cmd := range commands { fmt.Fprintf(os.Stderr, " %s", cmd.name) if cmd.params != "" { fmt.Fprintf(os.Stderr, " %s", cmd.params) } fmt.Fprintf(os.Stderr, "\n") } fmt.Fprintf(os.Stderr, "\n") } dbConfigsFile, dbCredentialsFile := dbconfigs.RegisterCommonFlags() flag.Parse() if err := relog.SetLevelByName(*logLevel); err != nil { relog.Fatal("%v", err) } tabletAddr = fmt.Sprintf("%v:%v", "localhost", *port) mycnf := mysqlctl.NewMycnf(uint32(*tabletUid), *mysqlPort, mysqlctl.VtReplParams{}) if *mysqlSocket != "" { mycnf.SocketFile = *mysqlSocket } dbcfgs, err := dbconfigs.Init(mycnf.SocketFile, *dbConfigsFile, *dbCredentialsFile) if err != nil { relog.Fatal("%v", err) } mysqld := mysqlctl.NewMysqld(mycnf, dbcfgs.Dba, dbcfgs.Repl) action := flag.Arg(0) for _, cmd := range commands { if cmd.name == action { subFlags := flag.NewFlagSet(action, flag.ExitOnError) subFlags.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s %s %s\n\n", os.Args[0], cmd.name, cmd.params) fmt.Fprintf(os.Stderr, "%s\n\n", cmd.help) subFlags.PrintDefaults() } cmd.method(mysqld, subFlags, flag.Args()[1:]) return } } relog.Fatal("invalid action: %v", action) }
func main() { defer logutil.Flush() flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s [global parameters] command [command parameters]\n", os.Args[0]) fmt.Fprintf(os.Stderr, "\nThe global optional parameters are:\n") flag.PrintDefaults() fmt.Fprintf(os.Stderr, "\nThe commands are listed below. Use '%s <command> -h' for more help.\n\n", os.Args[0]) for _, cmd := range commands { fmt.Fprintf(os.Stderr, " %s", cmd.name) if cmd.params != "" { fmt.Fprintf(os.Stderr, " %s", cmd.params) } fmt.Fprintf(os.Stderr, "\n") } fmt.Fprintf(os.Stderr, "\n") } dbconfigs.RegisterFlags() flag.Parse() tabletAddr = fmt.Sprintf("%v:%v", "localhost", *port) mycnf := mysqlctl.NewMycnf(uint32(*tabletUid), *mysqlPort) if *mysqlSocket != "" { mycnf.SocketFile = *mysqlSocket } dbcfgs, err := dbconfigs.Init(mycnf.SocketFile) if err != nil { log.Fatalf("%v", err) } mysqld := mysqlctl.NewMysqld("Dba", mycnf, &dbcfgs.Dba, &dbcfgs.Repl) defer mysqld.Close() action := flag.Arg(0) for _, cmd := range commands { if cmd.name == action { subFlags := flag.NewFlagSet(action, flag.ExitOnError) subFlags.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s %s %s\n\n", os.Args[0], cmd.name, cmd.params) fmt.Fprintf(os.Stderr, "%s\n\n", cmd.help) subFlags.PrintDefaults() } cmd.method(mysqld, subFlags, flag.Args()[1:]) return } } log.Fatalf("invalid action: %v", action) }
// StartServer starts the server and initializes // all the global variables. This function should only be called // once at the beginning of the test. func StartServer(connParams sqldb.ConnParams) error { dbcfgs := dbconfigs.DBConfigs{ App: dbconfigs.DBConfig{ ConnParams: connParams, Keyspace: "vttest", Shard: "0", }, } mysqld := mysqlctl.NewMysqld( "Dba", "App", &mysqlctl.Mycnf{}, &dbcfgs.Dba, &dbcfgs.App.ConnParams, &dbcfgs.Repl) BaseConfig = tabletserver.DefaultQsConfig BaseConfig.EnableAutoCommit = true BaseConfig.StrictTableAcl = true Target = querypb.Target{ Keyspace: "vttest", Shard: "0", TabletType: topodatapb.TabletType_MASTER, } Server = tabletserver.NewTabletServer(BaseConfig) Server.Register() err := Server.StartService(Target, dbcfgs, mysqld) if err != nil { return fmt.Errorf("could not start service: %v\n", err) } // Start http service. ln, err := net.Listen("tcp", ":0") if err != nil { return fmt.Errorf("could not start listener: %v\n", err) } ServerAddress = fmt.Sprintf("http://%s", ln.Addr().String()) go http.Serve(ln, nil) for { time.Sleep(10 * time.Millisecond) response, err := http.Get(fmt.Sprintf("%s/debug/vars", ServerAddress)) if err == nil { response.Body.Close() break } } return nil }
func (util *testUtils) newMysqld(dbconfigs *dbconfigs.DBConfigs) mysqlctl.MysqlDaemon { cnf := mysqlctl.NewMycnf(11111, 6802) // Assigning ServerID to be different from tablet UID to make sure that there are no // assumptions in the code that those IDs are the same. cnf.ServerID = 22222 return mysqlctl.NewMysqld( cnf, &dbconfigs.Dba, &dbconfigs.AllPrivs, &dbconfigs.App, &dbconfigs.Repl, false, /* enablePublishStats */ ) }
func (util *testUtils) newMysqld(dbconfigs *dbconfigs.DBConfigs) mysqlctl.MysqlDaemon { cnf := mysqlctl.NewMycnf(11111, 6802) // Assigning ServerID to be different from tablet UID to make sure that there are no // assumptions in the code that those IDs are the same. cnf.ServerID = 22222 return mysqlctl.NewMysqld( "", "", cnf, &dbconfigs.Dba, &dbconfigs.App.ConnParams, &dbconfigs.Repl, ) }
func main() { dbconfigs.RegisterFlags() mysqlctl.RegisterFlags() flag.Parse() servenv.Init() defer servenv.Close() log.Infof("started vtaction %v", os.Args) servenv.ServeRPC() mycnf, mycnfErr := mysqlctl.NewMycnfFromFlags(0) if mycnfErr != nil { log.Fatalf("mycnf read failed: %v", mycnfErr) } log.V(6).Infof("mycnf: %v", jscfg.ToJson(mycnf)) dbcfgs, cfErr := dbconfigs.Init(mycnf.SocketFile) if cfErr != nil { log.Fatalf("%s", cfErr) } mysqld := mysqlctl.NewMysqld("Dba", mycnf, &dbcfgs.Dba, &dbcfgs.Repl) defer mysqld.Close() topoServer := topo.GetServer() defer topo.CloseServers() actor := actor.NewTabletActor(mysqld, mysqld, topoServer, topo.TabletAlias{}) // we delegate out startup to the micromanagement server so these actions // will occur after we have obtained our socket. bindAddr := fmt.Sprintf(":%v", *servenv.Port) httpServer := &http.Server{Addr: bindAddr} go func() { if err := httpServer.ListenAndServe(); err != nil { log.Errorf("httpServer.ListenAndServe err: %v", err) } }() actionErr := actor.HandleAction(*actionNode, *action, *actionGuid, *force) if actionErr != nil { log.Fatalf("action error: %v", actionErr) } log.Infof("finished vtaction %v", os.Args) }
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() }
// NewActionAgent creates a new ActionAgent and registers all the // associated services func NewActionAgent( tabletAlias topo.TabletAlias, dbcfgs *dbconfigs.DBConfigs, mycnf *mysqlctl.Mycnf, port, securePort int, overridesFile string, ) (agent *ActionAgent, err error) { schemaOverrides := loadSchemaOverrides(overridesFile) topoServer := topo.GetServer() mysqld := mysqlctl.NewMysqld(mycnf, &dbcfgs.Dba, &dbcfgs.Repl) agent = &ActionAgent{ TopoServer: topoServer, TabletAlias: tabletAlias, Mysqld: mysqld, DBConfigs: dbcfgs, SchemaOverrides: schemaOverrides, done: make(chan struct{}), History: history.New(historyLength), changeItems: make(chan tabletChangeItem, 100), } // Start the binlog player services, not playing at start. agent.BinlogPlayerMap = NewBinlogPlayerMap(topoServer, &dbcfgs.App.ConnectionParams, mysqld) RegisterBinlogPlayerMap(agent.BinlogPlayerMap) 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 agent.initHeathCheck() return agent, nil }
func main() { defer exit.Recover() defer logutil.Flush() flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s [global parameters] command [command parameters]\n", os.Args[0]) fmt.Fprintf(os.Stderr, "\nThe global optional parameters are:\n") flag.PrintDefaults() fmt.Fprintf(os.Stderr, "\nThe commands are listed below. Use '%s <command> -h' for more help.\n\n", os.Args[0]) for _, cmd := range commands { fmt.Fprintf(os.Stderr, " %s", cmd.name) if cmd.params != "" { fmt.Fprintf(os.Stderr, " %s", cmd.params) } fmt.Fprintf(os.Stderr, "\n") } fmt.Fprintf(os.Stderr, "\n") } flags := dbconfigs.AppConfig | dbconfigs.DbaConfig | dbconfigs.FilteredConfig | dbconfigs.ReplConfig dbconfigs.RegisterFlags(flags) flag.Parse() tabletAddr = netutil.JoinHostPort("localhost", int32(*port)) 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(1) } mysqld := mysqlctl.NewMysqld("Dba", "App", mycnf, &dbcfgs.Dba, &dbcfgs.App.ConnParams, &dbcfgs.Repl) defer mysqld.Close() action := flag.Arg(0) for _, cmd := range commands { if cmd.name == action { subFlags := flag.NewFlagSet(action, flag.ExitOnError) subFlags.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s %s %s\n\n", os.Args[0], cmd.name, cmd.params) fmt.Fprintf(os.Stderr, "%s\n\n", cmd.help) subFlags.PrintDefaults() } if err := cmd.method(mysqld, subFlags, flag.Args()[1:]); err != nil { log.Error(err) exit.Return(1) } return } } log.Errorf("invalid action: %v", action) exit.Return(1) }
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() { 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.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() }
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() // 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() }
// 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 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() 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() }
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() }
// 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 }