Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
20490caaf0 | ||
![]() |
e156746959 | ||
![]() |
d84bf983cc | ||
![]() |
b44c6bff9d | ||
![]() |
8c3c1b4a9c | ||
![]() |
b478387a59 | ||
![]() |
dfc1f21f9d |
@@ -5,6 +5,12 @@ ADD etcdctl /usr/local/bin/
|
||||
RUN mkdir -p /var/etcd/
|
||||
RUN mkdir -p /var/lib/etcd/
|
||||
|
||||
# Alpine Linux doesn't use pam, which means that there is no /etc/nsswitch.conf,
|
||||
# but Golang relies on /etc/nsswitch.conf to check the order of DNS resolving
|
||||
# (see https://github.com/golang/go/commit/9dee7771f561cf6aee081c0af6658cc81fac3918)
|
||||
# To fix this we just create /etc/nsswitch.conf and add the following line:
|
||||
RUN echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf
|
||||
|
||||
EXPOSE 2379 2380
|
||||
|
||||
# Define default command.
|
||||
|
@@ -132,6 +132,8 @@ type watchGrpcStream struct {
|
||||
errc chan error
|
||||
// closingc gets the watcherStream of closing watchers
|
||||
closingc chan *watcherStream
|
||||
// wg is Done when all substream goroutines have exited
|
||||
wg sync.WaitGroup
|
||||
|
||||
// resumec closes to signal that all substreams should begin resuming
|
||||
resumec chan struct{}
|
||||
@@ -406,7 +408,7 @@ func (w *watchGrpcStream) run() {
|
||||
for range closing {
|
||||
w.closeSubstream(<-w.closingc)
|
||||
}
|
||||
|
||||
w.wg.Wait()
|
||||
w.owner.closeStream(w)
|
||||
}()
|
||||
|
||||
@@ -431,6 +433,7 @@ func (w *watchGrpcStream) run() {
|
||||
}
|
||||
|
||||
ws.donec = make(chan struct{})
|
||||
w.wg.Add(1)
|
||||
go w.serveSubstream(ws, w.resumec)
|
||||
|
||||
// queue up for watcher creation/resume
|
||||
@@ -576,6 +579,7 @@ func (w *watchGrpcStream) serveSubstream(ws *watcherStream, resumec chan struct{
|
||||
if !resuming {
|
||||
w.closingc <- ws
|
||||
}
|
||||
w.wg.Done()
|
||||
}()
|
||||
|
||||
emptyWr := &WatchResponse{}
|
||||
@@ -674,6 +678,7 @@ func (w *watchGrpcStream) newWatchClient() (pb.Watch_WatchClient, error) {
|
||||
continue
|
||||
}
|
||||
ws.donec = make(chan struct{})
|
||||
w.wg.Add(1)
|
||||
go w.serveSubstream(ws, w.resumec)
|
||||
}
|
||||
|
||||
|
@@ -19,7 +19,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/coreos/etcd/etcdserver"
|
||||
"github.com/coreos/etcd/etcdserver/api/v2http"
|
||||
@@ -166,7 +166,7 @@ func startPeerListeners(cfg *Config) (plns []net.Listener, err error) {
|
||||
for i, u := range cfg.LPUrls {
|
||||
phosts[i] = u.Host
|
||||
}
|
||||
cfg.PeerTLSInfo, err = transport.SelfCert(path.Join(cfg.Dir, "fixtures/peer"), phosts)
|
||||
cfg.PeerTLSInfo, err = transport.SelfCert(filepath.Join(cfg.Dir, "fixtures", "peer"), phosts)
|
||||
if err != nil {
|
||||
plog.Fatalf("could not get certs (%v)", err)
|
||||
}
|
||||
@@ -221,7 +221,7 @@ func startClientListeners(cfg *Config) (sctxs map[string]*serveCtx, err error) {
|
||||
for i, u := range cfg.LCUrls {
|
||||
chosts[i] = u.Host
|
||||
}
|
||||
cfg.ClientTLSInfo, err = transport.SelfCert(path.Join(cfg.Dir, "fixtures/client"), chosts)
|
||||
cfg.ClientTLSInfo, err = transport.SelfCert(filepath.Join(cfg.Dir, "fixtures", "client"), chosts)
|
||||
if err != nil {
|
||||
plog.Fatalf("could not get certs (%v)", err)
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@
|
||||
package embed
|
||||
|
||||
import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/coreos/etcd/wal"
|
||||
)
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
func isMemberInitialized(cfg *Config) bool {
|
||||
waldir := cfg.WalDir
|
||||
if waldir == "" {
|
||||
waldir = path.Join(cfg.Dir, "member", "wal")
|
||||
waldir = filepath.Join(cfg.Dir, "member", "wal")
|
||||
}
|
||||
|
||||
return wal.Exist(waldir)
|
||||
|
@@ -17,7 +17,7 @@ package command
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||
@@ -50,19 +50,19 @@ func handleBackup(c *cli.Context) error {
|
||||
var srcWAL string
|
||||
var destWAL string
|
||||
|
||||
srcSnap := path.Join(c.String("data-dir"), "member", "snap")
|
||||
destSnap := path.Join(c.String("backup-dir"), "member", "snap")
|
||||
srcSnap := filepath.Join(c.String("data-dir"), "member", "snap")
|
||||
destSnap := filepath.Join(c.String("backup-dir"), "member", "snap")
|
||||
|
||||
if c.String("wal-dir") != "" {
|
||||
srcWAL = c.String("wal-dir")
|
||||
} else {
|
||||
srcWAL = path.Join(c.String("data-dir"), "member", "wal")
|
||||
srcWAL = filepath.Join(c.String("data-dir"), "member", "wal")
|
||||
}
|
||||
|
||||
if c.String("backup-wal-dir") != "" {
|
||||
destWAL = c.String("backup-wal-dir")
|
||||
} else {
|
||||
destWAL = path.Join(c.String("backup-dir"), "member", "wal")
|
||||
destWAL = filepath.Join(c.String("backup-dir"), "member", "wal")
|
||||
}
|
||||
|
||||
if err := fileutil.CreateDirAll(destSnap); err != nil {
|
||||
|
@@ -21,7 +21,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/client"
|
||||
@@ -103,7 +103,7 @@ func prepareBackend() backend.Backend {
|
||||
var be backend.Backend
|
||||
|
||||
bch := make(chan struct{})
|
||||
dbpath := path.Join(migrateDatadir, "member", "snap", "db")
|
||||
dbpath := filepath.Join(migrateDatadir, "member", "snap", "db")
|
||||
go func() {
|
||||
defer close(bch)
|
||||
be = backend.New(dbpath, time.Second, 10000)
|
||||
@@ -130,9 +130,9 @@ func rebuildStoreV2() (store.Store, uint64) {
|
||||
|
||||
waldir := migrateWALdir
|
||||
if len(waldir) == 0 {
|
||||
waldir = path.Join(migrateDatadir, "member", "wal")
|
||||
waldir = filepath.Join(migrateDatadir, "member", "wal")
|
||||
}
|
||||
snapdir := path.Join(migrateDatadir, "member", "snap")
|
||||
snapdir := filepath.Join(migrateDatadir, "member", "snap")
|
||||
|
||||
ss := snap.New(snapdir)
|
||||
snapshot, err := ss.Load()
|
||||
|
@@ -23,7 +23,7 @@ import (
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
@@ -186,8 +186,8 @@ func snapshotRestoreCommandFunc(cmd *cobra.Command, args []string) {
|
||||
basedir = restoreName + ".etcd"
|
||||
}
|
||||
|
||||
waldir := path.Join(basedir, "member", "wal")
|
||||
snapdir := path.Join(basedir, "member", "snap")
|
||||
waldir := filepath.Join(basedir, "member", "wal")
|
||||
snapdir := filepath.Join(basedir, "member", "snap")
|
||||
|
||||
if _, err := os.Stat(basedir); err == nil {
|
||||
ExitWithError(ExitInvalidInput, fmt.Errorf("data-dir %q exists", basedir))
|
||||
@@ -325,7 +325,7 @@ func makeDB(snapdir, dbfile string, commit int) {
|
||||
ExitWithError(ExitIO, err)
|
||||
}
|
||||
|
||||
dbpath := path.Join(snapdir, "db")
|
||||
dbpath := filepath.Join(snapdir, "db")
|
||||
db, dberr := os.OpenFile(dbpath, os.O_RDWR|os.O_CREATE, 0600)
|
||||
if dberr != nil {
|
||||
ExitWithError(ExitIO, dberr)
|
||||
|
@@ -22,7 +22,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
@@ -211,14 +211,14 @@ func startProxy(cfg *config) error {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg.Dir = path.Join(cfg.Dir, "proxy")
|
||||
cfg.Dir = filepath.Join(cfg.Dir, "proxy")
|
||||
err = os.MkdirAll(cfg.Dir, fileutil.PrivateDirMode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var peerURLs []string
|
||||
clusterfile := path.Join(cfg.Dir, "cluster")
|
||||
clusterfile := filepath.Join(cfg.Dir, "cluster")
|
||||
|
||||
b, err := ioutil.ReadFile(clusterfile)
|
||||
switch {
|
||||
|
@@ -16,7 +16,7 @@ package etcdserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -118,16 +118,16 @@ func (c *ServerConfig) advertiseMatchesCluster() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ServerConfig) MemberDir() string { return path.Join(c.DataDir, "member") }
|
||||
func (c *ServerConfig) MemberDir() string { return filepath.Join(c.DataDir, "member") }
|
||||
|
||||
func (c *ServerConfig) WALDir() string {
|
||||
if c.DedicatedWALDir != "" {
|
||||
return c.DedicatedWALDir
|
||||
}
|
||||
return path.Join(c.MemberDir(), "wal")
|
||||
return filepath.Join(c.MemberDir(), "wal")
|
||||
}
|
||||
|
||||
func (c *ServerConfig) SnapDir() string { return path.Join(c.MemberDir(), "snap") }
|
||||
func (c *ServerConfig) SnapDir() string { return filepath.Join(c.MemberDir(), "snap") }
|
||||
|
||||
func (c *ServerConfig) ShouldDiscover() bool { return c.DiscoveryURL != "" }
|
||||
|
||||
|
@@ -23,6 +23,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@@ -263,7 +264,7 @@ func NewServer(cfg *ServerConfig) (srv *EtcdServer, err error) {
|
||||
}
|
||||
ss := snap.New(cfg.SnapDir())
|
||||
|
||||
bepath := path.Join(cfg.SnapDir(), databaseFilename)
|
||||
bepath := filepath.Join(cfg.SnapDir(), databaseFilename)
|
||||
beExist := fileutil.Exist(bepath)
|
||||
|
||||
var be backend.Backend
|
||||
@@ -791,7 +792,7 @@ func (s *EtcdServer) applySnapshot(ep *etcdProgress, apply *apply) {
|
||||
plog.Panicf("get database snapshot file path error: %v", err)
|
||||
}
|
||||
|
||||
fn := path.Join(s.Cfg.SnapDir(), databaseFilename)
|
||||
fn := filepath.Join(s.Cfg.SnapDir(), databaseFilename)
|
||||
if err := os.Rename(snapfn, fn); err != nil {
|
||||
plog.Panicf("rename snapshot file error: %v", err)
|
||||
}
|
||||
|
@@ -18,7 +18,7 @@ import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -58,7 +58,7 @@ func TestEmbedEtcd(t *testing.T) {
|
||||
setupEmbedCfg(&tests[5].cfg, []url.URL{urls[4]}, []url.URL{urls[5], urls[6]})
|
||||
setupEmbedCfg(&tests[6].cfg, []url.URL{urls[7], urls[8]}, []url.URL{urls[9]})
|
||||
|
||||
dir := path.Join(os.TempDir(), fmt.Sprintf("embed-etcd"))
|
||||
dir := filepath.Join(os.TempDir(), fmt.Sprintf("embed-etcd"))
|
||||
os.RemoveAll(dir)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
|
@@ -18,7 +18,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"sync"
|
||||
@@ -400,5 +400,5 @@ func NewTestBackend(t *testing.T) (string, backend.Backend) {
|
||||
t.Fatalf("failed to create tmpdir (%v)", err)
|
||||
}
|
||||
|
||||
return tmpPath, backend.New(path.Join(tmpPath, "be"), time.Second, 10000)
|
||||
return tmpPath, backend.New(filepath.Join(tmpPath, "be"), time.Second, 10000)
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@@ -337,7 +337,7 @@ func NewTmpBackend(batchInterval time.Duration, batchLimit int) (*backend, strin
|
||||
if err != nil {
|
||||
plog.Fatal(err)
|
||||
}
|
||||
tmpPath := path.Join(dir, "database")
|
||||
tmpPath := filepath.Join(dir, "database")
|
||||
return newBackend(tmpPath, batchInterval, batchLimit), tmpPath
|
||||
}
|
||||
|
||||
|
@@ -19,7 +19,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"github.com/coreos/pkg/capnslog"
|
||||
@@ -39,7 +39,7 @@ var (
|
||||
// IsDirWriteable checks if dir is writable by writing and removing a file
|
||||
// to dir. It returns nil if dir is writable.
|
||||
func IsDirWriteable(dir string) error {
|
||||
f := path.Join(dir, ".touch")
|
||||
f := filepath.Join(dir, ".touch")
|
||||
if err := ioutil.WriteFile(f, []byte(""), PrivateFileMode); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@ package fileutil
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -45,7 +45,7 @@ func purgeFile(dirname string, suffix string, max uint, interval time.Duration,
|
||||
sort.Strings(newfnames)
|
||||
fnames = newfnames
|
||||
for len(newfnames) > int(max) {
|
||||
f := path.Join(dirname, newfnames[0])
|
||||
f := filepath.Join(dirname, newfnames[0])
|
||||
l, err := TryLockFile(f, os.O_WRONLY, PrivateFileMode)
|
||||
if err != nil {
|
||||
break
|
||||
|
@@ -18,7 +18,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -33,7 +33,7 @@ func TestPurgeFile(t *testing.T) {
|
||||
|
||||
// minimal file set
|
||||
for i := 0; i < 3; i++ {
|
||||
f, ferr := os.Create(path.Join(dir, fmt.Sprintf("%d.test", i)))
|
||||
f, ferr := os.Create(filepath.Join(dir, fmt.Sprintf("%d.test", i)))
|
||||
if ferr != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -53,7 +53,7 @@ func TestPurgeFile(t *testing.T) {
|
||||
// rest of the files
|
||||
for i := 4; i < 10; i++ {
|
||||
go func(n int) {
|
||||
f, ferr := os.Create(path.Join(dir, fmt.Sprintf("%d.test", n)))
|
||||
f, ferr := os.Create(filepath.Join(dir, fmt.Sprintf("%d.test", n)))
|
||||
if ferr != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -99,7 +99,7 @@ func TestPurgeFileHoldingLockFile(t *testing.T) {
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
var f *os.File
|
||||
f, err = os.Create(path.Join(dir, fmt.Sprintf("%d.test", i)))
|
||||
f, err = os.Create(filepath.Join(dir, fmt.Sprintf("%d.test", i)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -107,7 +107,7 @@ func TestPurgeFileHoldingLockFile(t *testing.T) {
|
||||
}
|
||||
|
||||
// create a purge barrier at 5
|
||||
p := path.Join(dir, fmt.Sprintf("%d.test", 5))
|
||||
p := filepath.Join(dir, fmt.Sprintf("%d.test", 5))
|
||||
l, err := LockFile(p, os.O_WRONLY, PrivateFileMode)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@@ -27,7 +27,7 @@ import (
|
||||
"math/big"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -91,8 +91,8 @@ func SelfCert(dirpath string, hosts []string) (info TLSInfo, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
certPath := path.Join(dirpath, "cert.pem")
|
||||
keyPath := path.Join(dirpath, "key.pem")
|
||||
certPath := filepath.Join(dirpath, "cert.pem")
|
||||
keyPath := filepath.Join(dirpath, "key.pem")
|
||||
_, errcert := os.Stat(certPath)
|
||||
_, errkey := os.Stat(keyPath)
|
||||
if errcert == nil && errkey == nil {
|
||||
|
@@ -1246,6 +1246,55 @@ func TestHandleHeartbeatResp(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestRaftFreesReadOnlyMem ensures raft will free read request from
|
||||
// readOnly readIndexQueue and pendingReadIndex map.
|
||||
// related issue: https://github.com/coreos/etcd/issues/7571
|
||||
func TestRaftFreesReadOnlyMem(t *testing.T) {
|
||||
sm := newTestRaft(1, []uint64{1, 2}, 5, 1, NewMemoryStorage())
|
||||
sm.becomeCandidate()
|
||||
sm.becomeLeader()
|
||||
sm.raftLog.commitTo(sm.raftLog.lastIndex())
|
||||
|
||||
ctx := []byte("ctx")
|
||||
|
||||
// leader starts linearizable read request.
|
||||
// more info: raft dissertation 6.4, step 2.
|
||||
sm.Step(pb.Message{From: 2, Type: pb.MsgReadIndex, Entries: []pb.Entry{{Data: ctx}}})
|
||||
msgs := sm.readMessages()
|
||||
if len(msgs) != 1 {
|
||||
t.Fatalf("len(msgs) = %d, want 1", len(msgs))
|
||||
}
|
||||
if msgs[0].Type != pb.MsgHeartbeat {
|
||||
t.Fatalf("type = %v, want MsgHeartbeat", msgs[0].Type)
|
||||
}
|
||||
if !bytes.Equal(msgs[0].Context, ctx) {
|
||||
t.Fatalf("Context = %v, want %v", msgs[0].Context, ctx)
|
||||
}
|
||||
if len(sm.readOnly.readIndexQueue) != 1 {
|
||||
t.Fatalf("len(readIndexQueue) = %v, want 1", len(sm.readOnly.readIndexQueue))
|
||||
}
|
||||
if len(sm.readOnly.pendingReadIndex) != 1 {
|
||||
t.Fatalf("len(pendingReadIndex) = %v, want 1", len(sm.readOnly.pendingReadIndex))
|
||||
}
|
||||
if _, ok := sm.readOnly.pendingReadIndex[string(ctx)]; !ok {
|
||||
t.Fatalf("can't find context %v in pendingReadIndex ", ctx)
|
||||
}
|
||||
|
||||
// heartbeat responses from majority of followers (1 in this case)
|
||||
// acknowledge the authority of the leader.
|
||||
// more info: raft dissertation 6.4, step 3.
|
||||
sm.Step(pb.Message{From: 2, Type: pb.MsgHeartbeatResp, Context: ctx})
|
||||
if len(sm.readOnly.readIndexQueue) != 0 {
|
||||
t.Fatalf("len(readIndexQueue) = %v, want 0", len(sm.readOnly.readIndexQueue))
|
||||
}
|
||||
if len(sm.readOnly.pendingReadIndex) != 0 {
|
||||
t.Fatalf("len(pendingReadIndex) = %v, want 0", len(sm.readOnly.pendingReadIndex))
|
||||
}
|
||||
if _, ok := sm.readOnly.pendingReadIndex[string(ctx)]; ok {
|
||||
t.Fatalf("found context %v in pendingReadIndex, want none", ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// TestMsgAppRespWaitReset verifies the resume behavior of a leader
|
||||
// MsgAppResp.
|
||||
func TestMsgAppRespWaitReset(t *testing.T) {
|
||||
|
@@ -100,7 +100,7 @@ func (ro *readOnly) advance(m pb.Message) []*readIndexStatus {
|
||||
if found {
|
||||
ro.readIndexQueue = ro.readIndexQueue[i:]
|
||||
for _, rs := range rss {
|
||||
delete(ro.pendingReadIndex, string(rs.req.Context))
|
||||
delete(ro.pendingReadIndex, string(rs.req.Entries[0].Data))
|
||||
}
|
||||
return rss
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/coreos/etcd/pkg/fileutil"
|
||||
)
|
||||
@@ -41,7 +41,7 @@ func (s *Snapshotter) SaveDBFrom(r io.Reader, id uint64) (int64, error) {
|
||||
os.Remove(f.Name())
|
||||
return n, err
|
||||
}
|
||||
fn := path.Join(s.dir, fmt.Sprintf("%016x.snap.db", id))
|
||||
fn := filepath.Join(s.dir, fmt.Sprintf("%016x.snap.db", id))
|
||||
if fileutil.Exist(fn) {
|
||||
os.Remove(f.Name())
|
||||
return n, nil
|
||||
@@ -67,7 +67,7 @@ func (s *Snapshotter) DBFilePath(id uint64) (string, error) {
|
||||
wfn := fmt.Sprintf("%016x.snap.db", id)
|
||||
for _, fn := range fns {
|
||||
if fn == wfn {
|
||||
return path.Join(s.dir, fn), nil
|
||||
return filepath.Join(s.dir, fn), nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("snap: snapshot file doesn't exist")
|
||||
|
@@ -21,7 +21,7 @@ import (
|
||||
"hash/crc32"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -84,13 +84,13 @@ func (s *Snapshotter) save(snapshot *raftpb.Snapshot) error {
|
||||
marshallingDurations.Observe(float64(time.Since(start)) / float64(time.Second))
|
||||
}
|
||||
|
||||
err = pioutil.WriteAndSyncFile(path.Join(s.dir, fname), d, 0666)
|
||||
err = pioutil.WriteAndSyncFile(filepath.Join(s.dir, fname), d, 0666)
|
||||
if err == nil {
|
||||
saveDurations.Observe(float64(time.Since(start)) / float64(time.Second))
|
||||
} else {
|
||||
err1 := os.Remove(path.Join(s.dir, fname))
|
||||
err1 := os.Remove(filepath.Join(s.dir, fname))
|
||||
if err1 != nil {
|
||||
plog.Errorf("failed to remove broken snapshot file %s", path.Join(s.dir, fname))
|
||||
plog.Errorf("failed to remove broken snapshot file %s", filepath.Join(s.dir, fname))
|
||||
}
|
||||
}
|
||||
return err
|
||||
@@ -114,7 +114,7 @@ func (s *Snapshotter) Load() (*raftpb.Snapshot, error) {
|
||||
}
|
||||
|
||||
func loadSnap(dir, name string) (*raftpb.Snapshot, error) {
|
||||
fpath := path.Join(dir, name)
|
||||
fpath := filepath.Join(dir, name)
|
||||
snap, err := Read(fpath)
|
||||
if err != nil {
|
||||
renameBroken(fpath)
|
||||
|
@@ -19,7 +19,7 @@ import (
|
||||
"hash/crc32"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
@@ -38,7 +38,7 @@ var testSnap = &raftpb.Snapshot{
|
||||
}
|
||||
|
||||
func TestSaveAndLoad(t *testing.T) {
|
||||
dir := path.Join(os.TempDir(), "snapshot")
|
||||
dir := filepath.Join(os.TempDir(), "snapshot")
|
||||
err := os.Mkdir(dir, 0700)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -60,7 +60,7 @@ func TestSaveAndLoad(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBadCRC(t *testing.T) {
|
||||
dir := path.Join(os.TempDir(), "snapshot")
|
||||
dir := filepath.Join(os.TempDir(), "snapshot")
|
||||
err := os.Mkdir(dir, 0700)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -76,14 +76,14 @@ func TestBadCRC(t *testing.T) {
|
||||
// fake a crc mismatch
|
||||
crcTable = crc32.MakeTable(crc32.Koopman)
|
||||
|
||||
_, err = Read(path.Join(dir, fmt.Sprintf("%016x-%016x.snap", 1, 1)))
|
||||
_, err = Read(filepath.Join(dir, fmt.Sprintf("%016x-%016x.snap", 1, 1)))
|
||||
if err == nil || err != ErrCRCMismatch {
|
||||
t.Errorf("err = %v, want %v", err, ErrCRCMismatch)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFailback(t *testing.T) {
|
||||
dir := path.Join(os.TempDir(), "snapshot")
|
||||
dir := filepath.Join(os.TempDir(), "snapshot")
|
||||
err := os.Mkdir(dir, 0700)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -91,7 +91,7 @@ func TestFailback(t *testing.T) {
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
large := fmt.Sprintf("%016x-%016x-%016x.snap", 0xFFFF, 0xFFFF, 0xFFFF)
|
||||
err = ioutil.WriteFile(path.Join(dir, large), []byte("bad data"), 0666)
|
||||
err = ioutil.WriteFile(filepath.Join(dir, large), []byte("bad data"), 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -109,7 +109,7 @@ func TestFailback(t *testing.T) {
|
||||
if !reflect.DeepEqual(g, testSnap) {
|
||||
t.Errorf("snap = %#v, want %#v", g, testSnap)
|
||||
}
|
||||
if f, err := os.Open(path.Join(dir, large) + ".broken"); err != nil {
|
||||
if f, err := os.Open(filepath.Join(dir, large) + ".broken"); err != nil {
|
||||
t.Fatal("broken snapshot does not exist")
|
||||
} else {
|
||||
f.Close()
|
||||
@@ -117,7 +117,7 @@ func TestFailback(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSnapNames(t *testing.T) {
|
||||
dir := path.Join(os.TempDir(), "snapshot")
|
||||
dir := filepath.Join(os.TempDir(), "snapshot")
|
||||
err := os.Mkdir(dir, 0700)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -125,7 +125,7 @@ func TestSnapNames(t *testing.T) {
|
||||
defer os.RemoveAll(dir)
|
||||
for i := 1; i <= 5; i++ {
|
||||
var f *os.File
|
||||
if f, err = os.Create(path.Join(dir, fmt.Sprintf("%d.snap", i))); err != nil {
|
||||
if f, err = os.Create(filepath.Join(dir, fmt.Sprintf("%d.snap", i))); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
f.Close()
|
||||
@@ -146,7 +146,7 @@ func TestSnapNames(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLoadNewestSnap(t *testing.T) {
|
||||
dir := path.Join(os.TempDir(), "snapshot")
|
||||
dir := filepath.Join(os.TempDir(), "snapshot")
|
||||
err := os.Mkdir(dir, 0700)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -175,7 +175,7 @@ func TestLoadNewestSnap(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNoSnapshot(t *testing.T) {
|
||||
dir := path.Join(os.TempDir(), "snapshot")
|
||||
dir := filepath.Join(os.TempDir(), "snapshot")
|
||||
err := os.Mkdir(dir, 0700)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -189,19 +189,19 @@ func TestNoSnapshot(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEmptySnapshot(t *testing.T) {
|
||||
dir := path.Join(os.TempDir(), "snapshot")
|
||||
dir := filepath.Join(os.TempDir(), "snapshot")
|
||||
err := os.Mkdir(dir, 0700)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
err = ioutil.WriteFile(path.Join(dir, "1.snap"), []byte(""), 0x700)
|
||||
err = ioutil.WriteFile(filepath.Join(dir, "1.snap"), []byte(""), 0x700)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = Read(path.Join(dir, "1.snap"))
|
||||
_, err = Read(filepath.Join(dir, "1.snap"))
|
||||
if err != ErrEmptySnapshot {
|
||||
t.Errorf("err = %v, want %v", err, ErrEmptySnapshot)
|
||||
}
|
||||
@@ -210,14 +210,14 @@ func TestEmptySnapshot(t *testing.T) {
|
||||
// TestAllSnapshotBroken ensures snapshotter returns
|
||||
// ErrNoSnapshot if all the snapshots are broken.
|
||||
func TestAllSnapshotBroken(t *testing.T) {
|
||||
dir := path.Join(os.TempDir(), "snapshot")
|
||||
dir := filepath.Join(os.TempDir(), "snapshot")
|
||||
err := os.Mkdir(dir, 0700)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
err = ioutil.WriteFile(path.Join(dir, "1.snap"), []byte("bad"), 0x700)
|
||||
err = ioutil.WriteFile(filepath.Join(dir, "1.snap"), []byte("bad"), 0x700)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@@ -18,7 +18,7 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||
@@ -58,7 +58,7 @@ func main() {
|
||||
ss := snap.New(snapDir(*from))
|
||||
snapshot, err = ss.Load()
|
||||
} else {
|
||||
snapshot, err = snap.Read(path.Join(snapDir(*from), *snapfile))
|
||||
snapshot, err = snap.Read(filepath.Join(snapDir(*from), *snapfile))
|
||||
}
|
||||
|
||||
switch err {
|
||||
@@ -132,9 +132,9 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func walDir(dataDir string) string { return path.Join(dataDir, "member", "wal") }
|
||||
func walDir(dataDir string) string { return filepath.Join(dataDir, "member", "wal") }
|
||||
|
||||
func snapDir(dataDir string) string { return path.Join(dataDir, "member", "snap") }
|
||||
func snapDir(dataDir string) string { return filepath.Join(dataDir, "member", "snap") }
|
||||
|
||||
func parseWALMetadata(b []byte) (id, cid types.ID) {
|
||||
var metadata etcdserverpb.Metadata
|
||||
|
@@ -26,7 +26,7 @@ import (
|
||||
var (
|
||||
// MinClusterVersion is the min cluster version this etcd binary is compatible with.
|
||||
MinClusterVersion = "3.0.0"
|
||||
Version = "3.1.4"
|
||||
Version = "3.1.5"
|
||||
APIVersion = "unknown"
|
||||
|
||||
// Git SHA Value will be set during build
|
||||
|
@@ -17,7 +17,7 @@ package wal
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/coreos/etcd/pkg/fileutil"
|
||||
)
|
||||
@@ -65,7 +65,7 @@ func (fp *filePipeline) Close() error {
|
||||
|
||||
func (fp *filePipeline) alloc() (f *fileutil.LockedFile, err error) {
|
||||
// count % 2 so this file isn't the same as the one last published
|
||||
fpath := path.Join(fp.dir, fmt.Sprintf("%d.tmp", fp.count%2))
|
||||
fpath := filepath.Join(fp.dir, fmt.Sprintf("%d.tmp", fp.count%2))
|
||||
if f, err = fileutil.LockFile(fpath, os.O_CREATE|os.O_WRONLY, fileutil.PrivateFileMode); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ package wal
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/coreos/etcd/pkg/fileutil"
|
||||
"github.com/coreos/etcd/wal/walpb"
|
||||
@@ -94,6 +94,6 @@ func openLast(dirpath string) (*fileutil.LockedFile, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
last := path.Join(dirpath, names[len(names)-1])
|
||||
last := filepath.Join(dirpath, names[len(names)-1])
|
||||
return fileutil.LockFile(last, os.O_RDWR, fileutil.PrivateFileMode)
|
||||
}
|
||||
|
18
wal/wal.go
18
wal/wal.go
@@ -21,7 +21,7 @@ import (
|
||||
"hash/crc32"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -97,7 +97,7 @@ func Create(dirpath string, metadata []byte) (*WAL, error) {
|
||||
}
|
||||
|
||||
// keep temporary wal directory so WAL initialization appears atomic
|
||||
tmpdirpath := path.Clean(dirpath) + ".tmp"
|
||||
tmpdirpath := filepath.Clean(dirpath) + ".tmp"
|
||||
if fileutil.Exist(tmpdirpath) {
|
||||
if err := os.RemoveAll(tmpdirpath); err != nil {
|
||||
return nil, err
|
||||
@@ -107,7 +107,7 @@ func Create(dirpath string, metadata []byte) (*WAL, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p := path.Join(tmpdirpath, walName(0, 0))
|
||||
p := filepath.Join(tmpdirpath, walName(0, 0))
|
||||
f, err := fileutil.LockFile(p, os.O_WRONLY|os.O_CREATE, fileutil.PrivateFileMode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -143,7 +143,7 @@ func Create(dirpath string, metadata []byte) (*WAL, error) {
|
||||
}
|
||||
|
||||
// directory was renamed; sync parent dir to persist rename
|
||||
pdir, perr := fileutil.OpenDir(path.Dir(w.dir))
|
||||
pdir, perr := fileutil.OpenDir(filepath.Dir(w.dir))
|
||||
if perr != nil {
|
||||
return nil, perr
|
||||
}
|
||||
@@ -196,7 +196,7 @@ func openAtIndex(dirpath string, snap walpb.Snapshot, write bool) (*WAL, error)
|
||||
rs := make([]io.Reader, 0)
|
||||
ls := make([]*fileutil.LockedFile, 0)
|
||||
for _, name := range names[nameIndex:] {
|
||||
p := path.Join(dirpath, name)
|
||||
p := filepath.Join(dirpath, name)
|
||||
if write {
|
||||
l, err := fileutil.TryLockFile(p, os.O_RDWR, fileutil.PrivateFileMode)
|
||||
if err != nil {
|
||||
@@ -232,7 +232,7 @@ func openAtIndex(dirpath string, snap walpb.Snapshot, write bool) (*WAL, error)
|
||||
// write reuses the file descriptors from read; don't close so
|
||||
// WAL can append without dropping the file lock
|
||||
w.readClose = nil
|
||||
if _, _, err := parseWalName(path.Base(w.tail().Name())); err != nil {
|
||||
if _, _, err := parseWalName(filepath.Base(w.tail().Name())); err != nil {
|
||||
closer()
|
||||
return nil, err
|
||||
}
|
||||
@@ -372,7 +372,7 @@ func (w *WAL) cut() error {
|
||||
return err
|
||||
}
|
||||
|
||||
fpath := path.Join(w.dir, walName(w.seq()+1, w.enti+1))
|
||||
fpath := filepath.Join(w.dir, walName(w.seq()+1, w.enti+1))
|
||||
|
||||
// create a temp wal file with name sequence + 1, or truncate the existing one
|
||||
newTail, err := w.fp.Open()
|
||||
@@ -464,7 +464,7 @@ func (w *WAL) ReleaseLockTo(index uint64) error {
|
||||
found := false
|
||||
|
||||
for i, l := range w.locks {
|
||||
_, lockIndex, err := parseWalName(path.Base(l.Name()))
|
||||
_, lockIndex, err := parseWalName(filepath.Base(l.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -611,7 +611,7 @@ func (w *WAL) seq() uint64 {
|
||||
if t == nil {
|
||||
return 0
|
||||
}
|
||||
seq, _, err := parseWalName(path.Base(t.Name()))
|
||||
seq, _, err := parseWalName(filepath.Base(t.Name()))
|
||||
if err != nil {
|
||||
plog.Fatalf("bad wal name %s (%v)", t.Name(), err)
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
@@ -40,7 +40,7 @@ func TestNew(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("err = %v, want nil", err)
|
||||
}
|
||||
if g := path.Base(w.tail().Name()); g != walName(0, 0) {
|
||||
if g := filepath.Base(w.tail().Name()); g != walName(0, 0) {
|
||||
t.Errorf("name = %+v, want %+v", g, walName(0, 0))
|
||||
}
|
||||
defer w.Close()
|
||||
@@ -51,7 +51,7 @@ func TestNew(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
gd := make([]byte, off)
|
||||
f, err := os.Open(path.Join(p, path.Base(w.tail().Name())))
|
||||
f, err := os.Open(filepath.Join(p, filepath.Base(w.tail().Name())))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -90,7 +90,7 @@ func TestNewForInitedDir(t *testing.T) {
|
||||
}
|
||||
defer os.RemoveAll(p)
|
||||
|
||||
os.Create(path.Join(p, walName(0, 0)))
|
||||
os.Create(filepath.Join(p, walName(0, 0)))
|
||||
if _, err = Create(p, nil); err == nil || err != os.ErrExist {
|
||||
t.Errorf("err = %v, want %v", err, os.ErrExist)
|
||||
}
|
||||
@@ -103,7 +103,7 @@ func TestOpenAtIndex(t *testing.T) {
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
f, err := os.Create(path.Join(dir, walName(0, 0)))
|
||||
f, err := os.Create(filepath.Join(dir, walName(0, 0)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -113,7 +113,7 @@ func TestOpenAtIndex(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("err = %v, want nil", err)
|
||||
}
|
||||
if g := path.Base(w.tail().Name()); g != walName(0, 0) {
|
||||
if g := filepath.Base(w.tail().Name()); g != walName(0, 0) {
|
||||
t.Errorf("name = %+v, want %+v", g, walName(0, 0))
|
||||
}
|
||||
if w.seq() != 0 {
|
||||
@@ -122,7 +122,7 @@ func TestOpenAtIndex(t *testing.T) {
|
||||
w.Close()
|
||||
|
||||
wname := walName(2, 10)
|
||||
f, err = os.Create(path.Join(dir, wname))
|
||||
f, err = os.Create(filepath.Join(dir, wname))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -132,7 +132,7 @@ func TestOpenAtIndex(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("err = %v, want nil", err)
|
||||
}
|
||||
if g := path.Base(w.tail().Name()); g != wname {
|
||||
if g := filepath.Base(w.tail().Name()); g != wname {
|
||||
t.Errorf("name = %+v, want %+v", g, wname)
|
||||
}
|
||||
if w.seq() != 2 {
|
||||
@@ -172,7 +172,7 @@ func TestCut(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wname := walName(1, 1)
|
||||
if g := path.Base(w.tail().Name()); g != wname {
|
||||
if g := filepath.Base(w.tail().Name()); g != wname {
|
||||
t.Errorf("name = %s, want %s", g, wname)
|
||||
}
|
||||
|
||||
@@ -188,14 +188,14 @@ func TestCut(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wname = walName(2, 2)
|
||||
if g := path.Base(w.tail().Name()); g != wname {
|
||||
if g := filepath.Base(w.tail().Name()); g != wname {
|
||||
t.Errorf("name = %s, want %s", g, wname)
|
||||
}
|
||||
|
||||
// check the state in the last WAL
|
||||
// We do check before closing the WAL to ensure that Cut syncs the data
|
||||
// into the disk.
|
||||
f, err := os.Open(path.Join(p, wname))
|
||||
f, err := os.Open(filepath.Join(p, wname))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -254,7 +254,7 @@ func TestSaveWithCut(t *testing.T) {
|
||||
}
|
||||
defer neww.Close()
|
||||
wname := walName(1, index)
|
||||
if g := path.Base(neww.tail().Name()); g != wname {
|
||||
if g := filepath.Base(neww.tail().Name()); g != wname {
|
||||
t.Errorf("name = %s, want %s", g, wname)
|
||||
}
|
||||
|
||||
@@ -416,7 +416,7 @@ func TestRecoverAfterCut(t *testing.T) {
|
||||
}
|
||||
md.Close()
|
||||
|
||||
if err := os.Remove(path.Join(p, walName(4, 4))); err != nil {
|
||||
if err := os.Remove(filepath.Join(p, walName(4, 4))); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -570,7 +570,7 @@ func TestReleaseLockTo(t *testing.T) {
|
||||
}
|
||||
for i, l := range w.locks {
|
||||
var lockIndex uint64
|
||||
_, lockIndex, err = parseWalName(path.Base(l.Name()))
|
||||
_, lockIndex, err = parseWalName(filepath.Base(l.Name()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -588,7 +588,7 @@ func TestReleaseLockTo(t *testing.T) {
|
||||
if len(w.locks) != 1 {
|
||||
t.Errorf("len(w.locks) = %d, want %d", len(w.locks), 1)
|
||||
}
|
||||
_, lockIndex, err := parseWalName(path.Base(w.locks[0].Name()))
|
||||
_, lockIndex, err := parseWalName(filepath.Base(w.locks[0].Name()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -673,11 +673,11 @@ func TestRestartCreateWal(t *testing.T) {
|
||||
defer os.RemoveAll(p)
|
||||
|
||||
// make temporary directory so it looks like initialization is interrupted
|
||||
tmpdir := path.Clean(p) + ".tmp"
|
||||
tmpdir := filepath.Clean(p) + ".tmp"
|
||||
if err = os.Mkdir(tmpdir, fileutil.PrivateDirMode); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err = os.OpenFile(path.Join(tmpdir, "test"), os.O_WRONLY|os.O_CREATE, fileutil.PrivateFileMode); err != nil {
|
||||
if _, err = os.OpenFile(filepath.Join(tmpdir, "test"), os.O_WRONLY|os.O_CREATE, fileutil.PrivateFileMode); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -729,7 +729,7 @@ func TestOpenOnTornWrite(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
fn := path.Join(p, path.Base(w.tail().Name()))
|
||||
fn := filepath.Join(p, filepath.Base(w.tail().Name()))
|
||||
w.Close()
|
||||
|
||||
// clobber some entry with 0's to simulate a torn write
|
||||
|
Reference in New Issue
Block a user