// HttpHandleSnapshots handles the serving of files from the local tablet func HttpHandleSnapshots(mycnf *mysqlctl.Mycnf, uid uint32) { // make a list of paths we can serve HTTP traffic from. // we don't resolve them here to real paths, as they might not exits yet snapshotDir := mysqlctl.SnapshotDir(uid) allowedPaths := []string{ path.Join(vtenv.VtDataRoot(), "data"), mysqlctl.TabletDir(uid), mysqlctl.SnapshotDir(uid), mycnf.DataDir, mycnf.InnodbDataHomeDir, mycnf.InnodbLogGroupHomeDir, } // NOTE: trailing slash in pattern means we handle all paths with this prefix http.Handle(mysqlctl.SnapshotURLPath+"/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { handleSnapshot(w, r, snapshotDir, allowedPaths) })) }
func main() { defer exit.Recover() defer logutil.Flush() dbconfigFlags := dbconfigs.AppConfig | dbconfigs.DbaConfig | dbconfigs.FilteredConfig | dbconfigs.ReplConfig dbconfigs.RegisterFlags(dbconfigFlags) flag.Parse() // We'll register this OnTerm handler before mysqld starts, so we get notified // if mysqld dies on its own without us (or our RPC client) telling it to. mysqldTerminated := make(chan struct{}) onTermFunc := func() { close(mysqldTerminated) } // Start or Init mysqld as needed. ctx, cancel := context.WithTimeout(context.Background(), *waitTime) tabletDir := mysqlctl.TabletDir(uint32(*tabletUID)) if _, statErr := os.Stat(tabletDir); os.IsNotExist(statErr) { // Generate my.cnf from scratch and use it to find mysqld. log.Infof("tablet dir (%s) doesn't exist, initializing", tabletDir) var err error mysqld, err = mysqlctl.CreateMysqld(uint32(*tabletUID), *mysqlSocket, int32(*mysqlPort), dbconfigFlags) if err != nil { log.Errorf("failed to initialize mysql config: %v", err) exit.Return(1) } mysqld.OnTerm(onTermFunc) if err := mysqld.Init(ctx, *initDBSQLFile); err != nil { log.Errorf("failed to initialize mysql data dir and start mysqld: %v", err) exit.Return(1) } } else { // There ought to be an existing my.cnf, so use it to find mysqld. log.Infof("tablet dir (%s) already exists, starting without init", tabletDir) var err error mysqld, err = mysqlctl.OpenMysqld(uint32(*tabletUID), dbconfigFlags) if err != nil { log.Errorf("failed to find mysql config: %v", err) exit.Return(1) } mysqld.OnTerm(onTermFunc) if err := mysqld.Start(ctx); err != nil { log.Errorf("failed to start mysqld: %v", err) exit.Return(1) } } cancel() servenv.Init() defer servenv.Close() // Take mysqld down with us on SIGTERM before entering lame duck. servenv.OnTerm(func() { log.Infof("mysqlctl received SIGTERM, shutting down mysqld first") ctx := context.Background() mysqld.Shutdown(ctx, false) }) // Start RPC server and wait for SIGTERM. mysqlctldTerminated := make(chan struct{}) go func() { servenv.RunDefault() close(mysqlctldTerminated) }() select { case <-mysqldTerminated: log.Infof("mysqld shut down on its own, exiting mysqlctld") case <-mysqlctldTerminated: log.Infof("mysqlctld shut down gracefully") } }
func main() { dbConfigsFile, dbCredentialsFile := dbconfigs.RegisterCommonFlags() flag.Parse() if err := servenv.Init("vttablet"); err != nil { relog.Fatal("Error in servenv.Init: %s", err) } tabletAlias := tabletParamToTabletAlias(*tabletPath) mycnf := readMycnf(tabletAlias.Uid) dbcfgs, err := dbconfigs.Init(mycnf.SocketFile, *dbConfigsFile, *dbCredentialsFile) if err != nil { relog.Warning("%s", err) } dbcfgs.App.Memcache = *rowcache if err := jscfg.ReadJson(*overridesFile, &schemaOverrides); err != nil { relog.Warning("%s", err) } else { data, _ := json.MarshalIndent(schemaOverrides, "", " ") relog.Info("schemaOverrides: %s\n", data) } initQueryService(dbcfgs) initUpdateStreamService(mycnf) ts.RegisterCacheInvalidator() // depends on both query and updateStream err = initAgent(tabletAlias, dbcfgs, mycnf, *dbConfigsFile, *dbCredentialsFile) // depends on both query and updateStream if err != nil { relog.Fatal("%s", err) } 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() // make a list of paths we can serve HTTP traffic from. // we don't resolve them here to real paths, as they might not exits yet snapshotDir := mysqlctl.SnapshotDir(tabletAlias.Uid) allowedPaths := []string{ path.Join(vtenv.VtDataRoot(), "data"), mysqlctl.TabletDir(tabletAlias.Uid), snapshotDir, mycnf.DataDir, mycnf.InnodbDataHomeDir, mycnf.InnodbLogGroupHomeDir, } // NOTE: trailing slash in pattern means we handle all paths with this prefix http.Handle(mysqlctl.SnapshotURLPath+"/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { handleSnapshot(w, r, snapshotDir, allowedPaths) })) // we delegate out startup to the micromanagement server so these actions // will occur after we have obtained our socket. umgmt.SetLameDuckPeriod(float32(*lameDuckPeriod)) umgmt.SetRebindDelay(float32(*rebindDelay)) umgmt.AddStartupCallback(func() { umgmt.StartHttpServer(fmt.Sprintf(":%v", *port)) if *securePort != 0 { relog.Info("listening on secure port %v", *securePort) umgmt.StartHttpsServer(fmt.Sprintf(":%v", *securePort), *cert, *key, *caCert) } }) umgmt.AddStartupCallback(func() { c := make(chan os.Signal, 1) signal.Notify(c, syscall.SIGTERM) go func() { for sig := range c { umgmt.SigTermHandler(sig) } }() }) relog.Info("started vttablet %v", *port) umgmtSocket := fmt.Sprintf("/tmp/vttablet-%08x-umgmt.sock", *port) if umgmtErr := umgmt.ListenAndServe(umgmtSocket); umgmtErr != nil { relog.Error("umgmt.ListenAndServe err: %v", umgmtErr) } relog.Info("done") }