Mycnf cleanup - separated the code that reads it from that generates it. Standardized the

Mycnf struct and enforced correct initialization.
This commit is contained in:
Shruti Patil 2012-10-01 16:50:39 -07:00
Родитель c94437f155
Коммит d133a42d27
14 изменённых файлов: 279 добавлений и 243 удалений

Просмотреть файл

@ -1,9 +1,6 @@
# master.cnf parameters
#master-info-file=file_name
log-bin = {{.BinLogPath}}
log-bin-index = {{.BinLogIndexPath}}
log-slave-updates
sync_binlog = 1
# empty binlog-do-db seems to block replication
#binlog-do-db = {{.DatabaseName}}

Просмотреть файл

@ -3,6 +3,7 @@
relay-log = {{.RelayLogPath}}
relay-log-index = {{.RelayLogIndexPath}}
relay-log-info-file = {{.RelayLogInfoPath}}
master-info-file = {{.MasterInfoFile}}
# required if this master is chained
# probably safe to turn on all the time at the expense of some disk I/O
@ -15,6 +16,3 @@ log-slave-updates
# vt_enable_binlog_splitter_rbr = 1
# vt_shard_key_range_start = {{.StartKey}}
# vt_shard_key_range_end = {{.EndKey}}
# vt_enable_send_cache_invalidation = 1
# vt_host = {{.VtHost}} #localhost
# vt_port = {{.VtPort}} # 6702

Просмотреть файл

@ -9,6 +9,7 @@ import (
"code.google.com/p/vitess/go/vt/dbconfigs"
"code.google.com/p/vitess/go/vt/mysqlctl"
"flag"
"fmt"
"log"
"os"
)
@ -16,7 +17,7 @@ import (
var port = flag.Int("port", 6612, "vtocc port")
var force = flag.Bool("force", false, "force action")
var mysqlPort = flag.Int("mysql-port", 3306, "mysql port")
var tabletUid = flag.Int("tablet-uid", 41983, "tablet uid")
var tabletUid = flag.Uint("tablet-uid", 41983, "tablet uid")
var logLevel = flag.String("log.level", "WARNING", "set log level")
func main() {
@ -26,8 +27,8 @@ func main() {
relog.LogNameToLogLevel(*logLevel))
relog.SetLogger(logger)
vtRepl := mysqlctl.VtReplParams{TabletHost: "localhost", TabletPort: *port}
mycnf := mysqlctl.NewMycnf(uint(*tabletUid), *mysqlPort, vtRepl)
tabletAddr := fmt.Sprintf("%v:%v", "localhost", *port)
mycnf := mysqlctl.NewMycnf(uint32(*tabletUid), *mysqlPort, mysqlctl.VtReplParams{})
dbcfgs, err := dbconfigs.Init(mycnf)
if err != nil {
relog.Fatal("%s", err)
@ -49,7 +50,7 @@ func main() {
log.Fatalf("partialrestore failed: %v", err)
}
case "partialsnapshot":
_, err := mysqld.CreateSplitReplicaSource(flag.Arg(1), flag.Arg(2), flag.Arg(3), flag.Arg(4), vtRepl.TabletAddr(), false)
_, err := mysqld.CreateSplitReplicaSource(flag.Arg(1), flag.Arg(2), flag.Arg(3), flag.Arg(4), tabletAddr, false)
if err != nil {
log.Fatalf("partialsnapshot failed: %v", err)
}
@ -66,7 +67,7 @@ func main() {
log.Fatalf("failed shutdown mysql: %v", mysqlErr)
}
case "snapshot":
_, err := mysqld.CreateSnapshot(flag.Arg(1), vtRepl.TabletAddr(), false)
_, err := mysqld.CreateSnapshot(flag.Arg(1), tabletAddr, false)
if err != nil {
log.Fatalf("snapshot failed: %v", err)
}

Просмотреть файл

@ -14,6 +14,7 @@ import (
"os"
"os/signal"
"path"
"strconv"
"strings"
"syscall"
@ -75,7 +76,14 @@ func main() {
flag.Parse()
env.Init("vttablet")
mycnf := readMycnf()
_, tabletidStr := path.Split(*tabletPath)
tabletId, err := strconv.ParseUint(tabletidStr, 10, 32)
if err != nil {
relog.Fatal("Error converting tabletid to uint")
}
mycnf := readMycnf(uint32(tabletId))
dbcfgs, err := dbconfigs.Init(mycnf)
if err != nil {
relog.Warning("%s", err)
@ -100,7 +108,7 @@ func main() {
// NOTE: trailing slash in pattern means we handle all paths with this prefix
// FIXME(msolomon) this path needs to be obtained from the config.
http.Handle("/vt/snapshot/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
handleSnapshot(w, r, mycnf)
handleSnapshot(w, r, mysqlctl.SnapshotDir(uint32(tabletId)))
}))
// we delegate out startup to the micromanagement server so these actions
@ -140,10 +148,9 @@ func serveRPC() {
bsonrpc.ServeRPC()
}
func readMycnf() *mysqlctl.Mycnf {
func readMycnf(tabletId uint32) *mysqlctl.Mycnf {
if *mycnfFile == "" {
_, tabletid := path.Split(*tabletPath)
*mycnfFile = fmt.Sprintf("%s/vt_%s/my.cnf", mysqlctl.VtDataRoot, tabletid)
*mycnfFile = mysqlctl.MycnfFile(tabletId)
}
mycnf, mycnfErr := mysqlctl.ReadMycnf(*mycnfFile)
if mycnfErr != nil {
@ -214,9 +221,9 @@ func initQueryService(dbcfgs dbconfigs.DBConfigs) {
})
}
func handleSnapshot(rw http.ResponseWriter, req *http.Request, mycnf *mysqlctl.Mycnf) {
func handleSnapshot(rw http.ResponseWriter, req *http.Request, snapshotDir string) {
// FIXME(msolomon) some sort of security, no?
if strings.HasPrefix(req.URL.Path, mycnf.SnapshotDir) {
if strings.HasPrefix(req.URL.Path, snapshotDir) {
relog.Info("serve %v", req.URL.Path)
http.ServeFile(rw, req, req.URL.Path)
} else {

Просмотреть файл

@ -63,7 +63,7 @@ func main() {
relog.LogNameToLogLevel(*logLevel))
relog.SetLogger(logger)
zkConfig := zkctl.MakeZkConfigFromString(*zkCfg, *myId)
zkConfig := zkctl.MakeZkConfigFromString(*zkCfg, uint32(*myId))
zkd := zkctl.NewZkd(zkConfig)
action := flag.Arg(0)

Просмотреть файл

@ -233,13 +233,13 @@ func (mysqld *Mysqld) CreateSnapshot(dbName, sourceAddr string, allowHierarchica
}
var rs *ReplicaSource
dataFiles, snapshotErr := mysqld.createSnapshot(dbName, mysqld.config.SnapshotDir)
dataFiles, snapshotErr := mysqld.createSnapshot(dbName, mysqld.SnapshotDir)
if snapshotErr != nil {
relog.Error("CreateSnapshot failed: %v", snapshotErr)
} else {
rs = NewReplicaSource(sourceAddr, masterAddr, mysqld.replParams.Uname, mysqld.replParams.Pass,
dbName, dataFiles, replicationPosition)
rsFile := path.Join(mysqld.config.SnapshotDir, replicaSourceFile)
rsFile := path.Join(mysqld.SnapshotDir, replicaSourceFile)
if snapshotErr = writeJson(rsFile, rs); snapshotErr != nil {
relog.Error("CreateSnapshot failed: %v", snapshotErr)
}
@ -341,7 +341,7 @@ func (mysqld *Mysqld) RestoreFromSnapshot(replicaSource *ReplicaSource) error {
func (mysqld *Mysqld) fetchSnapshot(replicaSource *ReplicaSource) error {
replicaDbPath := path.Join(mysqld.config.DataDir, replicaSource.DbName)
cleanDirs := []string{mysqld.config.SnapshotDir, replicaDbPath,
cleanDirs := []string{mysqld.SnapshotDir, replicaDbPath,
mysqld.config.InnodbDataHomeDir, mysqld.config.InnodbLogGroupHomeDir}
// clean out and start fresh
@ -356,5 +356,5 @@ func (mysqld *Mysqld) fetchSnapshot(replicaSource *ReplicaSource) error {
}
}
return fetchFiles(replicaSource, mysqld.config.TabletDir)
return fetchFiles(replicaSource, mysqld.TabletDir)
}

Просмотреть файл

@ -11,143 +11,41 @@ package mysqlctl
import (
"bufio"
"bytes"
"fmt"
"io"
"io/ioutil"
"net"
"os"
"path"
"strconv"
"strings"
"text/template"
)
type VtReplParams struct {
TabletHost string
TabletPort int
StartKey string
EndKey string
}
func (vtrp VtReplParams) TabletAddr() string {
return fmt.Sprintf("%v:%v", vtrp.TabletHost, vtrp.TabletPort)
}
type Mycnf struct {
ServerId uint
TabletDir string
SnapshotDir string
ServerId uint32
MysqlPort int
DataDir string
MycnfFile string
InnodbDataHomeDir string
InnodbLogGroupHomeDir string
DatabaseName string // for replication FIXME(msolomon) should not be needed
SocketFile string
MysqlPort int
VtHost string
VtPort int
StartKey string
EndKey string
ErrorLogPath string
SlowLogPath string
RelayLogPath string
RelayLogIndexPath string
RelayLogInfoPath string
BinLogPath string
BinLogIndexPath string
MasterInfoFile string
PidFile string
mycnfMap map[string]string
}
const (
VtDataRoot = "/vt"
snapshotDir = "snapshot"
dataDir = "data"
innodbDir = "innodb"
relayLogDir = "relay-logs"
binLogDir = "bin-logs"
innodbDataSubdir = "innodb/data"
innodbLogSubdir = "innodb/log"
)
/* uid is a unique id for a particular tablet - it must be unique within the
tabletservers deployed within a keyspace, lest there be collisions on disk.
mysqldPort needs to be unique per instance per machine (shocking) but choosing
this sensibly has nothing to do with the config, so I'll punt.
*/
func NewMycnf(uid uint, mysqlPort int, vtRepl VtReplParams) *Mycnf {
cnf := new(Mycnf)
cnf.ServerId = uid
cnf.MysqlPort = mysqlPort
cnf.TabletDir = fmt.Sprintf("%s/vt_%010d", VtDataRoot, uid)
cnf.SnapshotDir = fmt.Sprintf("%s/%s/vt_%010d", VtDataRoot, snapshotDir, uid)
cnf.DataDir = path.Join(cnf.TabletDir, dataDir)
cnf.MycnfFile = path.Join(cnf.TabletDir, "my.cnf")
cnf.InnodbDataHomeDir = path.Join(cnf.TabletDir, innodbDataSubdir)
cnf.InnodbLogGroupHomeDir = path.Join(cnf.TabletDir, innodbLogSubdir)
cnf.SocketFile = path.Join(cnf.TabletDir, "mysql.sock")
cnf.VtHost = vtRepl.TabletHost
cnf.VtPort = vtRepl.TabletPort
cnf.StartKey = vtRepl.StartKey
cnf.EndKey = vtRepl.EndKey
return cnf
}
func (cnf *Mycnf) TopLevelDirs() []string {
return []string{dataDir, innodbDir, relayLogDir, binLogDir}
}
func (cnf *Mycnf) DirectoryList() []string {
return []string{
cnf.DataDir,
cnf.InnodbDataHomeDir,
cnf.InnodbLogGroupHomeDir,
cnf.relayLogDir(),
cnf.binLogDir(),
func (cnf *Mycnf) lookupAndCheck(key string) string {
val := cnf.mycnfMap[key]
if val == "" {
panic(fmt.Errorf("Value for key '%v' not set", key))
}
}
func (cnf *Mycnf) ErrorLogPath() string {
return path.Join(cnf.TabletDir, "error.log")
}
func (cnf *Mycnf) SlowLogPath() string {
return path.Join(cnf.TabletDir, "slow-query.log")
}
func (cnf *Mycnf) relayLogDir() string {
return path.Join(cnf.TabletDir, relayLogDir)
}
func (cnf *Mycnf) RelayLogPath() string {
return path.Join(cnf.relayLogDir(),
fmt.Sprintf("vt-%010d-relay-bin", cnf.ServerId))
}
func (cnf *Mycnf) RelayLogIndexPath() string {
return cnf.RelayLogPath() + ".index"
}
func (cnf *Mycnf) RelayLogInfoPath() string {
return path.Join(cnf.TabletDir, "relay-logs", "relay.info")
}
func (cnf *Mycnf) binLogDir() string {
return path.Join(cnf.TabletDir, binLogDir)
}
func (cnf *Mycnf) BinLogPath() string {
return path.Join(cnf.binLogDir(),
fmt.Sprintf("vt-%010d-bin", cnf.ServerId))
}
func (cnf *Mycnf) BinLogPathForId(fileid int) string {
return path.Join(cnf.binLogDir(),
fmt.Sprintf("vt-%010d-bin.%06d", cnf.ServerId, fileid))
}
func (cnf *Mycnf) BinLogIndexPath() string {
return cnf.BinLogPath() + ".index"
}
func (cnf *Mycnf) MasterInfoPath() string {
return path.Join(cnf.TabletDir, "master.info")
}
func (cnf *Mycnf) PidFile() string {
return path.Join(cnf.TabletDir, "mysql.pid")
return val
}
func (cnf *Mycnf) MysqlAddr() string {
@ -167,50 +65,13 @@ func fqdn() string {
return strings.TrimRight(cname, ".")
}
/*
Join cnf files cnfPaths and subsitute in the right values.
*/
func MakeMycnf(cnfFiles []string, mycnf *Mycnf, header string) (string, error) {
myTemplateSource := new(bytes.Buffer)
for _, line := range strings.Split(header, "\n") {
fmt.Fprintf(myTemplateSource, "## %v\n", strings.TrimSpace(line))
}
myTemplateSource.WriteString("[mysqld]\n")
for _, path := range cnfFiles {
data, dataErr := ioutil.ReadFile(path)
if dataErr != nil {
return "", dataErr
func ReadMycnf(cnfFile string) (mycnf *Mycnf, err error) {
defer func(err *error) {
if x := recover(); x != nil {
*err = x.(error)
}
myTemplateSource.WriteString("## " + path + "\n")
myTemplateSource.Write(data)
}
}(&err)
myTemplate, err := template.New("").Parse(myTemplateSource.String())
if err != nil {
return "", err
}
mycnfData := new(bytes.Buffer)
err = myTemplate.Execute(mycnfData, mycnf)
if err != nil {
return "", err
}
return mycnfData.String(), nil
}
/* Create a config for this instance. Search cnfFiles for the appropriate
cnf template files.
*/
func MakeMycnfForMysqld(mysqld *Mysqld, cnfFiles, header string) (string, error) {
// FIXME(msolomon) determine config list from mysqld struct
cnfs := []string{"default", "master", "replica"}
paths := make([]string, len(cnfs))
for i, name := range cnfs {
paths[i] = fmt.Sprintf("%v/%v.cnf", cnfFiles, name)
}
return MakeMycnf(paths, mysqld.config, header)
}
func ReadMycnf(cnfFile string) (*Mycnf, error) {
f, err := os.Open(cnfFile)
if err != nil {
return nil, err
@ -218,7 +79,10 @@ func ReadMycnf(cnfFile string) (*Mycnf, error) {
defer f.Close()
buf := bufio.NewReader(f)
mycnf := new(Mycnf)
mycnf = new(Mycnf)
mycnf.mycnfMap = make(map[string]string)
var lval, rval string
var parts [][]byte
for {
line, _, err := buf.ReadLine()
@ -226,37 +90,45 @@ func ReadMycnf(cnfFile string) (*Mycnf, error) {
break
}
line = bytes.TrimSpace(line)
if bytes.HasPrefix(line, []byte("server-id")) {
serverId, err := strconv.Atoi(string(bytes.TrimSpace(bytes.Split(line, []byte("="))[1])))
if err != nil {
return nil, fmt.Errorf("mycnf: failed to convert server-id %v", err)
}
mycnf.ServerId = uint(serverId)
} else if bytes.HasPrefix(line, []byte("port")) {
port, err := strconv.Atoi(string(bytes.TrimSpace(bytes.Split(line, []byte("="))[1])))
if err != nil {
return nil, fmt.Errorf("mycnf: failed to convert port %v", err)
}
mycnf.MysqlPort = port
} else if bytes.HasPrefix(line, []byte("datadir")) {
mycnf.DataDir = string(bytes.TrimSpace(bytes.Split(line, []byte("="))[1]))
} else if bytes.HasPrefix(line, []byte("innodb_log_group_home_dir")) {
mycnf.InnodbLogGroupHomeDir = string(bytes.TrimSpace(bytes.Split(line, []byte("="))[1]))
} else if bytes.HasPrefix(line, []byte("innodb_data_home_dir")) {
mycnf.InnodbDataHomeDir = string(bytes.TrimSpace(bytes.Split(line, []byte("="))[1]))
} else if bytes.HasPrefix(line, []byte("socket")) {
mycnf.SocketFile = string(bytes.TrimSpace(bytes.Split(line, []byte("="))[1]))
parts = bytes.Split(line, []byte("="))
if len(parts) < 2 {
continue
}
lval = string(bytes.TrimSpace(parts[0]))
rval = string(bytes.TrimSpace(parts[1]))
mycnf.mycnfMap[lval] = rval
}
// Make sure we run the correct initialization.
vtMycnf := NewMycnf(mycnf.ServerId, mycnf.MysqlPort, VtReplParams{})
serverIdStr := mycnf.lookupAndCheck("server-id")
serverId, err := strconv.Atoi(serverIdStr)
if err != nil {
panic(fmt.Errorf("Failed to convert server-id %v", err))
}
mycnf.ServerId = uint32(serverId)
// Apply overrides.
vtMycnf.DataDir = mycnf.DataDir
vtMycnf.InnodbDataHomeDir = mycnf.InnodbDataHomeDir
vtMycnf.InnodbLogGroupHomeDir = mycnf.InnodbLogGroupHomeDir
vtMycnf.SocketFile = mycnf.SocketFile
portStr := mycnf.lookupAndCheck("port")
port, err := strconv.Atoi(portStr)
if err != nil {
panic(fmt.Errorf("Failed: failed to convert port %v", err))
}
mycnf.MysqlPort = port
mycnf.DataDir = mycnf.lookupAndCheck("datadir")
mycnf.InnodbDataHomeDir = mycnf.lookupAndCheck("innodb_data_home_dir")
mycnf.InnodbLogGroupHomeDir = mycnf.lookupAndCheck("innodb_log_group_home_dir")
mycnf.SocketFile = mycnf.lookupAndCheck("socket")
mycnf.ErrorLogPath = mycnf.lookupAndCheck("log-error")
mycnf.SlowLogPath = mycnf.lookupAndCheck("slow-query-log-file")
mycnf.RelayLogPath = mycnf.lookupAndCheck("relay-log")
mycnf.RelayLogIndexPath = mycnf.lookupAndCheck("relay-log-index")
mycnf.RelayLogInfoPath = mycnf.lookupAndCheck("relay-log-info-file")
mycnf.BinLogPath = mycnf.lookupAndCheck("log-bin")
mycnf.BinLogIndexPath = mycnf.lookupAndCheck("log-bin-index")
mycnf.MasterInfoFile = mycnf.lookupAndCheck("master-info-file")
mycnf.PidFile = mycnf.lookupAndCheck("pid-file")
//These values are currently not being set, hence not checking them.
mycnf.StartKey = mycnf.mycnfMap["vt_shard_key_range_start"]
mycnf.EndKey = mycnf.mycnfMap["vt_shard_key_range_end"]
return vtMycnf, nil
return mycnf, nil
}

136
go/vt/mysqlctl/mycnf_gen.go Normal file
Просмотреть файл

@ -0,0 +1,136 @@
// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Generate my.cnf files from templates.
*/
package mysqlctl
import (
"bytes"
"fmt"
"io/ioutil"
"path"
"strings"
"text/template"
)
type VtReplParams struct {
StartKey string
EndKey string
}
const (
VtDataRoot = "/vt"
dataDir = "data"
innodbDir = "innodb"
relayLogDir = "relay-logs"
binLogDir = "bin-logs"
innodbDataSubdir = "innodb/data"
innodbLogSubdir = "innodb/log"
snapshotDir = "snapshot"
)
/*
NewMycnf fills the Mycnf structure with vt root paths and derived values.
This is used to fill out the cnfTemplate values and generate my.cnf.
uid is a unique id for a particular tablet - it must be unique within the
tabletservers deployed within a keyspace, lest there be collisions on disk.
mysqldPort needs to be unique per instance per machine.
*/
func NewMycnf(uid uint32, mysqlPort int, vtRepl VtReplParams) *Mycnf {
cnf := new(Mycnf)
tabletDir := TabletDir(uid)
cnf.ServerId = uid
cnf.MysqlPort = mysqlPort
cnf.DataDir = path.Join(tabletDir, dataDir)
cnf.InnodbDataHomeDir = path.Join(tabletDir, innodbDataSubdir)
cnf.InnodbLogGroupHomeDir = path.Join(tabletDir, innodbLogSubdir)
cnf.SocketFile = path.Join(tabletDir, "mysql.sock")
cnf.StartKey = vtRepl.StartKey
cnf.EndKey = vtRepl.EndKey
cnf.ErrorLogPath = path.Join(tabletDir, "error.log")
cnf.SlowLogPath = path.Join(tabletDir, "slow-query.log")
cnf.RelayLogPath = path.Join(tabletDir, relayLogDir,
fmt.Sprintf("vt-%010d-relay-bin", cnf.ServerId))
cnf.RelayLogIndexPath = cnf.RelayLogPath + ".index"
cnf.RelayLogInfoPath = path.Join(tabletDir, relayLogDir, "relay-log.info")
cnf.BinLogPath = path.Join(tabletDir, binLogDir,
fmt.Sprintf("vt-%010d-bin", cnf.ServerId))
cnf.BinLogIndexPath = cnf.BinLogPath + ".index"
cnf.MasterInfoFile = path.Join(tabletDir, "master.info")
cnf.PidFile = path.Join(tabletDir, "mysql.pid")
return cnf
}
func TabletDir(uid uint32) string {
return fmt.Sprintf("%s/vt_%010d", VtDataRoot, uid)
}
func SnapshotDir(uid uint32) string {
return fmt.Sprintf("%s/%s/vt_%010d", VtDataRoot, snapshotDir, uid)
}
func MycnfFile(uid uint32) string {
return path.Join(TabletDir(uid), "my.cnf")
}
func TopLevelDirs() []string {
return []string{dataDir, innodbDir, relayLogDir, binLogDir}
}
func DirectoryList(cnf *Mycnf) []string {
return []string{
cnf.DataDir,
cnf.InnodbDataHomeDir,
cnf.InnodbLogGroupHomeDir,
path.Join(TabletDir(cnf.ServerId), relayLogDir),
path.Join(TabletDir(cnf.ServerId), binLogDir),
}
}
/*
Join cnf files cnfPaths and subsitute in the right values.
*/
func MakeMycnf(cnfFiles []string, mycnf *Mycnf, header string) (string, error) {
myTemplateSource := new(bytes.Buffer)
for _, line := range strings.Split(header, "\n") {
fmt.Fprintf(myTemplateSource, "## %v\n", strings.TrimSpace(line))
}
myTemplateSource.WriteString("[mysqld]\n")
for _, path := range cnfFiles {
data, dataErr := ioutil.ReadFile(path)
if dataErr != nil {
return "", dataErr
}
myTemplateSource.WriteString("## " + path + "\n")
myTemplateSource.Write(data)
}
myTemplate, err := template.New("").Parse(myTemplateSource.String())
if err != nil {
return "", err
}
mycnfData := new(bytes.Buffer)
err = myTemplate.Execute(mycnfData, mycnf)
if err != nil {
return "", err
}
return mycnfData.String(), nil
}
/* Create a config for this instance. Search cnfFiles for the appropriate
cnf template files.
*/
func MakeMycnfForMysqld(mysqld *Mysqld, cnfFiles, header string) (string, error) {
// FIXME(msolomon) determine config list from mysqld struct
cnfs := []string{"default", "master", "replica"}
paths := make([]string, len(cnfs))
for i, name := range cnfs {
paths[i] = fmt.Sprintf("%v/%v.cnf", cnfFiles, name)
}
return MakeMycnf(paths, mysqld.config, header)
}

Просмотреть файл

@ -5,18 +5,19 @@
package mysqlctl
import (
"io/ioutil"
"os"
"testing"
)
var MYCNF_PATH = "/tmp/my.cnf"
func TestMycnf(t *testing.T) {
var vtRepl VtReplParams
vtRepl.TabletHost = "localhost"
vtRepl.TabletPort = 6702
vtRepl.StartKey = ""
vtRepl.EndKey = ""
tablet0 := NewMysqld(NewMycnf(0, 6802, "", vtRepl), DefaultDbaParams, DefaultReplParams)
tablet0 := NewMysqld(NewMycnf(0, 6802, vtRepl), DefaultDbaParams, DefaultReplParams)
cnfTemplatePath := os.ExpandEnv("$VTROOT/src/code.google.com/p/vitess/config/mycnf")
// FIXME(msolomon) make a path that has a chance of succeeding elsewhere
data, err := MakeMycnfForMysqld(tablet0, cnfTemplatePath, "test header")
@ -25,4 +26,19 @@ func TestMycnf(t *testing.T) {
} else {
t.Logf("data: %v", data)
}
err = ioutil.WriteFile(MYCNF_PATH, []byte(data), 0666)
if err != nil {
t.Errorf("failed creating my.cnf %v", err)
}
_, err = ioutil.ReadFile(MYCNF_PATH)
if err != nil {
t.Errorf("failed reading, err %v", err)
return
}
mycnf, err := ReadMycnf(MYCNF_PATH)
if err != nil {
t.Errorf("failed reading, err %v", err)
} else {
t.Logf("socket file %v", mycnf.SocketFile)
}
}

Просмотреть файл

@ -47,6 +47,9 @@ type Mysqld struct {
dbaParams mysql.ConnectionParams
replParams mysql.ConnectionParams
createConnection CreateConnection
TabletDir string
SnapshotDir string
MycnfFile string
}
func NewMysqld(config *Mycnf, dba, repl mysql.ConnectionParams) *Mysqld {
@ -57,8 +60,14 @@ func NewMysqld(config *Mycnf, dba, repl mysql.ConnectionParams) *Mysqld {
createSuperConnection := func() (*mysql.Connection, error) {
return mysql.Connect(dba)
}
return &Mysqld{config, dba, repl, createSuperConnection}
return &Mysqld{config,
dba,
repl,
createSuperConnection,
TabletDir(config.ServerId),
SnapshotDir(config.ServerId),
MycnfFile(config.ServerId),
}
}
func Start(mt *Mysqld) error {
@ -66,7 +75,7 @@ func Start(mt *Mysqld) error {
dir := os.ExpandEnv("$VT_MYSQL_ROOT")
name := dir + "/bin/mysqld_safe"
arg := []string{
"--defaults-file=" + mt.config.MycnfFile}
"--defaults-file=" + mt.MycnfFile}
env := []string{
os.ExpandEnv("LD_LIBRARY_PATH=$VT_MYSQL_ROOT/lib/mysql"),
}
@ -109,7 +118,7 @@ func Shutdown(mt *Mysqld, waitForMysqld bool) error {
relog.Info("mysqlctl.Shutdown")
// possibly mysql is already shutdown, check for a few files first
_, socketPathErr := os.Stat(mt.config.SocketFile)
_, pidPathErr := os.Stat(mt.config.PidFile())
_, pidPathErr := os.Stat(mt.config.PidFile)
if socketPathErr != nil && pidPathErr != nil {
relog.Warning("assuming shutdown - no socket, no pid file")
return nil
@ -170,10 +179,10 @@ func Init(mt *Mysqld) error {
cnfTemplatePath := os.ExpandEnv("$VTROOT/config/mycnf")
configData, err := MakeMycnfForMysqld(mt, cnfTemplatePath, "tablet uid?")
if err == nil {
err = ioutil.WriteFile(mt.config.MycnfFile, []byte(configData), 0664)
err = ioutil.WriteFile(mt.MycnfFile, []byte(configData), 0664)
}
if err != nil {
relog.Error("failed creating %v: %v", mt.config.MycnfFile, err)
relog.Error("failed creating %v: %v", mt.MycnfFile, err)
return err
}
@ -186,7 +195,7 @@ func Init(mt *Mysqld) error {
return tarErr
}
if err = Start(mt); err != nil {
relog.Error("failed starting, check %v", mt.config.ErrorLogPath())
relog.Error("failed starting, check %v", mt.config.ErrorLogPath)
return err
}
schemaPath := os.ExpandEnv("$VTROOT/data/bootstrap/_vt_schema.sql")
@ -209,16 +218,16 @@ func Init(mt *Mysqld) error {
}
func (mt *Mysqld) createDirs() error {
relog.Info("creating directory %s", mt.config.TabletDir)
if err := os.MkdirAll(mt.config.TabletDir, 0775); err != nil {
relog.Info("creating directory %s", mt.TabletDir)
if err := os.MkdirAll(mt.TabletDir, 0775); err != nil {
return err
}
for _, dir := range mt.config.TopLevelDirs() {
for _, dir := range TopLevelDirs() {
if err := mt.createTopDir(dir); err != nil {
return err
}
}
for _, dir := range mt.config.DirectoryList() {
for _, dir := range DirectoryList(mt.config) {
relog.Info("creating directory %s", dir)
if err := os.MkdirAll(dir, 0775); err != nil {
return err
@ -236,19 +245,19 @@ func (mt *Mysqld) createDirs() error {
// /vt/data/vt_xxxx
// /vt/vt_xxxx/data -> /vt/data/vt_xxxx
func (mt *Mysqld) createTopDir(dir string) error {
vtname := path.Base(mt.config.TabletDir)
vtname := path.Base(mt.TabletDir)
target := path.Join(VtDataRoot, dir)
_, err := os.Lstat(target)
if err != nil {
if err.(*os.PathError).Err == syscall.ENOENT {
topdir := path.Join(mt.config.TabletDir, dir)
topdir := path.Join(mt.TabletDir, dir)
relog.Info("creating directory %s", topdir)
return os.MkdirAll(topdir, 0775)
}
return err
}
linkto := path.Join(target, vtname)
source := path.Join(mt.config.TabletDir, dir)
source := path.Join(mt.TabletDir, dir)
relog.Info("creating directory %s", linkto)
err = os.MkdirAll(linkto, 0775)
if err != nil {
@ -267,8 +276,8 @@ func Teardown(mt *Mysqld, force bool) error {
}
}
var removalErr error
for _, dir := range mt.config.TopLevelDirs() {
qdir := path.Join(mt.config.TabletDir, dir)
for _, dir := range TopLevelDirs() {
qdir := path.Join(mt.TabletDir, dir)
if err := deleteTopDir(qdir); err != nil {
removalErr = err
}

Просмотреть файл

@ -9,8 +9,8 @@ import (
)
func TestStartShutdown(t *testing.T) {
mycnf0 := NewMycnf(0, 3700, "", VtReplParams{TabletHost: "localhost"})
mycnf1 := NewMycnf(1, 3701, "", VtReplParams{TabletHost: "localhost"})
mycnf0 := NewMycnf(0, 3700, VtReplParams{})
mycnf1 := NewMycnf(1, 3701, VtReplParams{})
tablet0 := NewMysqld(mycnf0, DefaultDbaParams, DefaultReplParams)
tablet1 := NewMysqld(mycnf1, DefaultDbaParams, DefaultReplParams)
var err error

Просмотреть файл

@ -115,12 +115,12 @@ func StartReplicationCommands(replState *ReplicationState) []string {
// Read replication state from local files.
func ReadReplicationState(mysqld *Mysqld) (*ReplicationState, error) {
relayInfo, err := ioutil.ReadFile(mysqld.config.RelayLogInfoPath())
relayInfo, err := ioutil.ReadFile(mysqld.config.RelayLogInfoPath)
if err != nil {
return nil, err
}
// FIXME(msolomon) not sure i'll need this data
masterInfo, err := ioutil.ReadFile(mysqld.config.MasterInfoPath())
masterInfo, err := ioutil.ReadFile(mysqld.config.MasterInfoFile)
if err != nil {
return nil, err
}

Просмотреть файл

@ -166,7 +166,7 @@ func (mysqld *Mysqld) CreateSplitReplicaSource(dbName, keyName, startKey, endKey
return
}
cloneSourcePath := path.Join(mysqld.config.SnapshotDir, dataDir, dbName+"-"+b64ForFilename(startKey)+","+b64ForFilename(endKey))
cloneSourcePath := path.Join(mysqld.SnapshotDir, dataDir, dbName+"-"+b64ForFilename(startKey)+","+b64ForFilename(endKey))
// clean out and start fresh
for _, _path := range []string{cloneSourcePath} {
if err = os.RemoveAll(_path); err != nil {
@ -262,7 +262,7 @@ func (mysqld *Mysqld) CreateSplitReplicaSource(dbName, keyName, startKey, endKey
} else {
rs = NewSplitReplicaSource(sourceAddr, masterAddr, mysqld.replParams.Uname, mysqld.replParams.Pass,
dbName, dataFiles, replicationPosition, startKey, endKey, schema)
rsFile := path.Join(mysqld.config.SnapshotDir, replicaSourceFile)
rsFile := path.Join(mysqld.SnapshotDir, replicaSourceFile)
if snapshotErr = writeJson(rsFile, rs); snapshotErr != nil {
relog.Error("CreateSnapshot failed: %v", snapshotErr)
}
@ -360,7 +360,7 @@ func (mysqld *Mysqld) RestoreFromPartialSnapshot(replicaSource *SplitReplicaSour
return
}
tempStoragePath := path.Join(mysqld.config.SnapshotDir, "partialrestore")
tempStoragePath := path.Join(mysqld.SnapshotDir, "partialrestore")
cleanDirs := []string{tempStoragePath}
// clean out and start fresh

Просмотреть файл

@ -21,7 +21,7 @@ import (
)
type zkServerAddr struct {
ServerId uint
ServerId uint32
Hostname string
LeaderPort int
ElectionPort int
@ -29,7 +29,7 @@ type zkServerAddr struct {
}
type ZkConfig struct {
ServerId uint
ServerId uint32
ClientPort int
Servers []zkServerAddr
Global bool
@ -121,7 +121,7 @@ const GUESS_MYID = 0
If server_id > 1000, then we assume this is a global quorum.
server_id's must be 1-255, global id's are 1001-1255 mod 1000.
*/
func MakeZkConfigFromString(cmdLine string, myId uint) *ZkConfig {
func MakeZkConfigFromString(cmdLine string, myId uint32) *ZkConfig {
zkConfig := NewZkConfig()
for _, zki := range strings.Split(cmdLine, ",") {
zkiParts := strings.SplitN(zki, "@", 2)
@ -137,7 +137,7 @@ func MakeZkConfigFromString(cmdLine string, myId uint) *ZkConfig {
}
myId = myId % 1000
zkServer := zkServerAddr{ServerId: uint(serverId), ClientPort: 2181,
zkServer := zkServerAddr{ServerId: uint32(serverId), ClientPort: 2181,
LeaderPort: 2888, ElectionPort: 3888}
switch len(zkAddrParts) {
case 4: