Compare commits
	
		
			6 Commits
		
	
	
		
			v3.6.0-alp
			...
			v2.0.5
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9481945228 | |||
| e13b09e4d9 | |||
| 78e0149f41 | |||
| 4c86ab4868 | |||
| 59327bab47 | |||
| 62ed1ebf03 | 
@ -30,7 +30,7 @@ ETCD_INITIAL_CLUSTER_STATE=new
 | 
				
			|||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
-initial-cluster infra0=http://10.0.1.10:2380,http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
 | 
					-initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
 | 
				
			||||||
  -initial-cluster-state new
 | 
					  -initial-cluster-state new
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,10 @@ func NewListener(addr string, scheme string, info TLSInfo) (net.Listener, error)
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !info.Empty() && scheme == "https" {
 | 
						if scheme == "https" {
 | 
				
			||||||
 | 
							if info.Empty() {
 | 
				
			||||||
 | 
								return nil, fmt.Errorf("cannot listen on TLS for %s: KeyFile and CertFile are not presented", scheme+"://"+addr)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		cfg, err := info.ServerConfig()
 | 
							cfg, err := info.ServerConfig()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
 | 
				
			|||||||
@ -70,6 +70,13 @@ func TestNewListenerTLSInfo(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestNewListenerTLSEmptyInfo(t *testing.T) {
 | 
				
			||||||
 | 
						_, err := NewListener("127.0.0.1:0", "https", TLSInfo{})
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							t.Errorf("err = nil, want not presented error")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestNewListenerTLSInfoNonexist(t *testing.T) {
 | 
					func TestNewListenerTLSInfoNonexist(t *testing.T) {
 | 
				
			||||||
	tlsInfo := TLSInfo{CertFile: "@badname", KeyFile: "@badname"}
 | 
						tlsInfo := TLSInfo{CertFile: "@badname", KeyFile: "@badname"}
 | 
				
			||||||
	_, err := NewListener("127.0.0.1:0", "https", tlsInfo)
 | 
						_, err := NewListener("127.0.0.1:0", "https", tlsInfo)
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,9 @@ func NewTimeoutTransport(info TLSInfo, rdtimeoutd, wtimeoutd time.Duration) (*ht
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						// the timeouted connection will tiemout soon after it is idle.
 | 
				
			||||||
 | 
						// it should not be put back to http transport as an idle connection for future usage.
 | 
				
			||||||
 | 
						tr.MaxIdleConnsPerHost = -1
 | 
				
			||||||
	tr.Dial = (&rwTimeoutDialer{
 | 
						tr.Dial = (&rwTimeoutDialer{
 | 
				
			||||||
		Dialer: net.Dialer{
 | 
							Dialer: net.Dialer{
 | 
				
			||||||
			Timeout:   30 * time.Second,
 | 
								Timeout:   30 * time.Second,
 | 
				
			||||||
 | 
				
			|||||||
@ -15,6 +15,8 @@
 | 
				
			|||||||
package transport
 | 
					package transport
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"net/http/httptest"
 | 
						"net/http/httptest"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
@ -28,7 +30,12 @@ func TestNewTimeoutTransport(t *testing.T) {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("unexpected NewTimeoutTransport error: %v", err)
 | 
							t.Fatalf("unexpected NewTimeoutTransport error: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	srv := httptest.NewServer(http.NotFoundHandler())
 | 
					
 | 
				
			||||||
 | 
						remoteAddr := func(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
							w.Write([]byte(r.RemoteAddr))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						srv := httptest.NewServer(http.HandlerFunc(remoteAddr))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	defer srv.Close()
 | 
						defer srv.Close()
 | 
				
			||||||
	conn, err := tr.Dial("tcp", srv.Listener.Addr().String())
 | 
						conn, err := tr.Dial("tcp", srv.Listener.Addr().String())
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -46,4 +53,33 @@ func TestNewTimeoutTransport(t *testing.T) {
 | 
				
			|||||||
	if tconn.wtimeoutd != time.Hour {
 | 
						if tconn.wtimeoutd != time.Hour {
 | 
				
			||||||
		t.Errorf("write timeout = %s, want %s", tconn.wtimeoutd, time.Hour)
 | 
							t.Errorf("write timeout = %s, want %s", tconn.wtimeoutd, time.Hour)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ensure not reuse timeout connection
 | 
				
			||||||
 | 
						req, err := http.NewRequest("GET", srv.URL, nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected err %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						resp, err := tr.RoundTrip(req)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected err %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						addr0, err := ioutil.ReadAll(resp.Body)
 | 
				
			||||||
 | 
						resp.Body.Close()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected err %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp, err = tr.RoundTrip(req)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected err %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						addr1, err := ioutil.ReadAll(resp.Body)
 | 
				
			||||||
 | 
						resp.Body.Close()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected err %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if bytes.Equal(addr0, addr1) {
 | 
				
			||||||
 | 
							t.Errorf("addr0 = %s addr1= %s, want not equal", string(addr0), string(addr1))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -304,7 +304,7 @@ func TestNodeStart(t *testing.T) {
 | 
				
			|||||||
	wants := []Ready{
 | 
						wants := []Ready{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			SoftState: &SoftState{Lead: 1, RaftState: StateLeader},
 | 
								SoftState: &SoftState{Lead: 1, RaftState: StateLeader},
 | 
				
			||||||
			HardState: raftpb.HardState{Term: 2, Commit: 2},
 | 
								HardState: raftpb.HardState{Term: 2, Commit: 2, Vote: 1},
 | 
				
			||||||
			Entries: []raftpb.Entry{
 | 
								Entries: []raftpb.Entry{
 | 
				
			||||||
				{Type: raftpb.EntryConfChange, Term: 1, Index: 1, Data: ccdata},
 | 
									{Type: raftpb.EntryConfChange, Term: 1, Index: 1, Data: ccdata},
 | 
				
			||||||
				{Term: 2, Index: 2},
 | 
									{Term: 2, Index: 2},
 | 
				
			||||||
@ -315,7 +315,7 @@ func TestNodeStart(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			HardState:        raftpb.HardState{Term: 2, Commit: 3},
 | 
								HardState:        raftpb.HardState{Term: 2, Commit: 3, Vote: 1},
 | 
				
			||||||
			Entries:          []raftpb.Entry{{Term: 2, Index: 3, Data: []byte("foo")}},
 | 
								Entries:          []raftpb.Entry{{Term: 2, Index: 3, Data: []byte("foo")}},
 | 
				
			||||||
			CommittedEntries: []raftpb.Entry{{Term: 2, Index: 3, Data: []byte("foo")}},
 | 
								CommittedEntries: []raftpb.Entry{{Term: 2, Index: 3, Data: []byte("foo")}},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
				
			|||||||
@ -306,9 +306,11 @@ func (r *raft) maybeCommit() bool {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (r *raft) reset(term uint64) {
 | 
					func (r *raft) reset(term uint64) {
 | 
				
			||||||
	r.Term = term
 | 
						if r.Term != term {
 | 
				
			||||||
 | 
							r.Term = term
 | 
				
			||||||
 | 
							r.Vote = None
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	r.lead = None
 | 
						r.lead = None
 | 
				
			||||||
	r.Vote = None
 | 
					 | 
				
			||||||
	r.elapsed = 0
 | 
						r.elapsed = 0
 | 
				
			||||||
	r.votes = make(map[uint64]bool)
 | 
						r.votes = make(map[uint64]bool)
 | 
				
			||||||
	for i := range r.prs {
 | 
						for i := range r.prs {
 | 
				
			||||||
 | 
				
			|||||||
@ -15,6 +15,6 @@
 | 
				
			|||||||
package version
 | 
					package version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	Version         = "2.0.4+git"
 | 
						Version         = "2.0.5"
 | 
				
			||||||
	InternalVersion = "2"
 | 
						InternalVersion = "2"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										37
									
								
								wal/wal.go
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								wal/wal.go
									
									
									
									
									
								
							@ -320,27 +320,34 @@ func (w *WAL) sync() error {
 | 
				
			|||||||
	return w.f.Sync()
 | 
						return w.f.Sync()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ReleaseLockTo releases the locks w is holding, which
 | 
					// ReleaseLockTo releases the locks, which has smaller index than the given index
 | 
				
			||||||
// have index smaller or equal to the given index.
 | 
					// except the largest one among them.
 | 
				
			||||||
 | 
					// For example, if WAL is holding lock 1,2,3,4,5,6, ReleaseLockTo(4) will release
 | 
				
			||||||
 | 
					// lock 1,2 but keep 3. ReleaseLockTo(5) will release 1,2,3 but keep 4.
 | 
				
			||||||
func (w *WAL) ReleaseLockTo(index uint64) error {
 | 
					func (w *WAL) ReleaseLockTo(index uint64) error {
 | 
				
			||||||
	for _, l := range w.locks {
 | 
						var smaller int
 | 
				
			||||||
		_, i, err := parseWalName(path.Base(l.Name()))
 | 
					
 | 
				
			||||||
 | 
						for i, l := range w.locks {
 | 
				
			||||||
 | 
							_, lockIndex, err := parseWalName(path.Base(l.Name()))
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if i > index {
 | 
							if lockIndex >= index {
 | 
				
			||||||
			return nil
 | 
								smaller = i - 1
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		err = l.Unlock()
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err = l.Destroy()
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		w.locks = w.locks[1:]
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if smaller <= 0 {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < smaller; i++ {
 | 
				
			||||||
 | 
							w.locks[i].Unlock()
 | 
				
			||||||
 | 
							w.locks[i].Destroy()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						w.locks = w.locks[smaller:]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -435,6 +435,7 @@ func TestOpenNotInUse(t *testing.T) {
 | 
				
			|||||||
	unlockIndex := uint64(5)
 | 
						unlockIndex := uint64(5)
 | 
				
			||||||
	w.ReleaseLockTo(unlockIndex)
 | 
						w.ReleaseLockTo(unlockIndex)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 1,2,3 are avaliable.
 | 
				
			||||||
	w2, err := OpenNotInUse(p, walpb.Snapshot{})
 | 
						w2, err := OpenNotInUse(p, walpb.Snapshot{})
 | 
				
			||||||
	defer w2.Close()
 | 
						defer w2.Close()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -444,8 +445,8 @@ func TestOpenNotInUse(t *testing.T) {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("err = %v, want nil", err)
 | 
							t.Fatalf("err = %v, want nil", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if g := ents[len(ents)-1].Index; g != unlockIndex {
 | 
						if g := ents[len(ents)-1].Index; g != unlockIndex-2 {
 | 
				
			||||||
		t.Errorf("last index read = %d, want %d", g, unlockIndex)
 | 
							t.Errorf("last index read = %d, want %d", g, unlockIndex-2)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -462,3 +463,45 @@ func TestSaveEmpty(t *testing.T) {
 | 
				
			|||||||
		t.Errorf("buf.Bytes = %d, want 0", len(buf.Bytes()))
 | 
							t.Errorf("buf.Bytes = %d, want 0", len(buf.Bytes()))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestReleaseLockTo(t *testing.T) {
 | 
				
			||||||
 | 
						p, err := ioutil.TempDir(os.TempDir(), "waltest")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer os.RemoveAll(p)
 | 
				
			||||||
 | 
						// create WAL
 | 
				
			||||||
 | 
						w, err := Create(p, nil)
 | 
				
			||||||
 | 
						defer w.Close()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// make 10 seperate files
 | 
				
			||||||
 | 
						for i := 0; i < 10; i++ {
 | 
				
			||||||
 | 
							es := []raftpb.Entry{{Index: uint64(i)}}
 | 
				
			||||||
 | 
							if err = w.Save(raftpb.HardState{}, es); err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err = w.Cut(); err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// release the lock to 5
 | 
				
			||||||
 | 
						unlockIndex := uint64(5)
 | 
				
			||||||
 | 
						w.ReleaseLockTo(unlockIndex)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// expected remaining are 4,5,6,7,8,9,10
 | 
				
			||||||
 | 
						if len(w.locks) != 7 {
 | 
				
			||||||
 | 
							t.Errorf("len(w.locks) = %d, want %d", len(w.locks), 7)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for i, l := range w.locks {
 | 
				
			||||||
 | 
							_, lockIndex, err := parseWalName(path.Base(l.Name()))
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if lockIndex != uint64(i+4) {
 | 
				
			||||||
 | 
								t.Errorf("#%d: lockindex = %d, want %d", i, lockIndex, uint64(i+4))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user