etcdserver: autodetect v0.4 WALs and upgrade them to v0.5 automatically

This commit is contained in:
Barak Michener 2014-11-18 13:43:20 -05:00
parent aca195f3ad
commit 78ea3335bf
2 changed files with 74 additions and 5 deletions

View File

@ -36,6 +36,7 @@ import (
"github.com/coreos/etcd/etcdserver/etcdhttp/httptypes"
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
"github.com/coreos/etcd/etcdserver/stats"
"github.com/coreos/etcd/migrate"
"github.com/coreos/etcd/pkg/pbutil"
"github.com/coreos/etcd/pkg/types"
"github.com/coreos/etcd/pkg/wait"
@ -190,18 +191,39 @@ type EtcdServer struct {
raftLead uint64
}
// UpgradeWAL converts an older version of the EtcdServer data to the newest version.
// It must ensure that, after upgrading, the most recent version is present.
func UpgradeWAL(cfg *ServerConfig, ver wal.WalVersion) {
if ver == wal.WALv0_4 {
err := migrate.Migrate4To5(cfg.DataDir, cfg.Name)
if err != nil {
log.Fatalf("Failed migrating data-dir: %v", err)
}
}
}
// NewServer creates a new EtcdServer from the supplied configuration. The
// configuration is considered static for the lifetime of the EtcdServer.
func NewServer(cfg *ServerConfig) (*EtcdServer, error) {
if err := os.MkdirAll(cfg.SnapDir(), privateDirMode); err != nil {
return nil, fmt.Errorf("cannot create snapshot directory: %v", err)
}
ss := snap.New(cfg.SnapDir())
st := store.New()
var w *wal.WAL
var n raft.Node
var id types.ID
haveWAL := wal.Exist(cfg.WALDir())
walVersion := wal.DetectVersion(cfg.DataDir)
if walVersion == wal.UnknownWAL {
return nil, fmt.Errorf("unknown wal version in data dir %s", cfg.DataDir)
}
haveWAL := walVersion != wal.NoWAL
if haveWAL && walVersion != wal.WALv0_5 {
UpgradeWAL(cfg, walVersion)
}
if err := os.MkdirAll(cfg.SnapDir(), privateDirMode); err != nil {
return nil, fmt.Errorf("cannot create snapshot directory: %v", err)
}
ss := snap.New(cfg.SnapDir())
switch {
case !haveWAL && !cfg.NewCluster:
us := getOtherPeerURLs(cfg.Cluster, cfg.Name)

View File

@ -20,8 +20,55 @@ import (
"fmt"
"log"
"os"
"path"
)
type StringSlice []string
func containsStrings(source, target []string) bool {
for _, t := range target {
ok := false
for _, s := range source {
if t == s {
ok = true
}
}
if !ok {
return false
}
}
return true
}
// WalVersion is an enum for versions of etcd logs.
type WalVersion string
const (
UnknownWAL WalVersion = "Unknown WAL"
NoWAL WalVersion = "No WAL"
WALv0_4 WalVersion = "0.4.x"
WALv0_5 WalVersion = "0.5.x"
)
func DetectVersion(dirpath string) WalVersion {
names, err := readDir(dirpath)
if err != nil || len(names) == 0 {
return NoWAL
}
if containsStrings(names, []string{"snap", "wal"}) {
// .../wal cannot be empty to exist.
if Exist(path.Join(dirpath, "wal")) {
return WALv0_5
}
return NoWAL
}
if containsStrings(names, []string{"snapshot", "conf", "log"}) {
return WALv0_4
}
return UnknownWAL
}
func Exist(dirpath string) bool {
names, err := readDir(dirpath)
if err != nil {