Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mvcc: fix TestHashKVWhenCompacting hash mismatch #8333

Merged
merged 4 commits into from
Aug 1, 2017

Conversation

fanminshi
Copy link
Member

@fanminshi fanminshi commented Jul 28, 2017

fixes #8311

@fanminshi
Copy link
Member Author

this pr allows HashKV to get compaction Keep without modifying the treeIndex.

Copy link
Contributor

@heyitsanthony heyitsanthony left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nothing calls Keep() outside of tests; please update hashkv in this patchset if that's why this is being introduced

mvcc/index.go Outdated
// Keep finds all revisions to be kept for a Compaction at the given rev.
func (ti *treeIndex) Keep(rev int64) map[revision]struct{} {
available := make(map[revision]struct{})
ti.Lock()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why isn't this RLock?

// remove any tombstone
if len(g.revs) == 1 && i != len(ki.generations)-1 {
if len(g.revs)-1 == n && i != len(ki.generations)-1 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

swapping the order of the if's doesn't look like it preserves the meaning; if n > 0 then delete(available, g.revs[0]) is not the same as the current code

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, the code should be delete(available, g.revs[n]) instead of delete(available, g.revs[0]).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why wasn't this caught by unit tests?

Copy link
Member Author

@fanminshi fanminshi Jul 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unit tests calls Compact before Keep where Compaction on tombstone clears out the generation. Then the subsequent Keep on the same tombstone rev will not even hit if len(g.revs)-1 == n && i != len(ki.generations)-1 { since if !g.isEmpty() { will be empty.

e.g

// Init Tree.
// key: "foo"
// rev: 16
// generations:
//    {empty}
//    {{14, 0}[1], {14, 1}[2], {16, 0}(t)[3]}
//    {{8, 0}[1], {10, 0}[2], {12, 0}(t)[3]}
//    {{2, 0}[1], {4, 0}[2], {6, 0}(t)[3]}

// Call Compact(12) keep = {}
// generations:
//    {empty}
//    {{14, 0}[1], {14, 1}[2], {16, 0}(t)[3]}

// Call Keep(12) keep = {} since there is no generation that contains rev 12.

I'll make unit test more strict.

ki.doCompact(atRev, available, false)
}

func (ki *keyIndex) doCompact(atRev int64, available map[revision]struct{}, doModify bool) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not good practice to have boolean arguments; possibly have
func (ki *keyIndex) doCompact(atRev int64, available map[revision]struct{}) (genIdx int, revIndex int) and handle the modification after calling doCompact

@@ -767,6 +767,10 @@ func (i *fakeIndex) Compact(rev int64) map[revision]struct{} {
i.Recorder.Record(testutil.Action{Name: "compact", Params: []interface{}{rev}})
return <-i.indexCompactRespc
}
func (i *fakeIndex) Keep(rev int64) map[revision]struct{} {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be in the same commit as the test update

}
keep := s.keep
s.keepMu.Unlock()
keep := s.kvindex.Keep(rev)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only need to acquire s.mu.RLock instead of s.mu.Lock now?

@fanminshi fanminshi changed the title mvcc: add Keep api to index mvcc: fix TestHashKVWhenCompacting hash mismatch Jul 31, 2017
Keep finds all revisions to be kept for a Compaction at the given rev.
@fanminshi
Copy link
Member Author

all fixed. PTAL.

Copy link
Contributor

@heyitsanthony heyitsanthony left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

}

func cloneGeneration(g *generation) *generation {
var tmp []revision
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use go built-ins:

tmp := make([]revision, len(g.revs))
copy(tmp, g.revs)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If g.revs is nil, the above code will create a non nil tmp which causes comparison failures.

--- FAIL: TestKeyIndexCompactAndKeep (0.00s)
	key_index_test.go:451: #0: ki = g: created[{2 0}] ver[3], revs []mvcc.revision{mvcc.revision{main:2, sub:0}, mvcc.revision{main:4, sub:0}, mvcc.revision{main:6, sub:0}}
		g: created[{8 0}] ver[3], revs []mvcc.revision{mvcc.revision{main:8, sub:0}, mvcc.revision{main:10, sub:0}, mvcc.revision{main:12, sub:0}}
		g: created[{14 0}] ver[3], revs []mvcc.revision{mvcc.revision{main:14, sub:0}, mvcc.revision{main:14, sub:1}, mvcc.revision{main:16, sub:0}}
		g: created[{0 0}] ver[0], revs []mvcc.revision(nil)
		, want g: created[{2 0}] ver[3], revs []mvcc.revision{mvcc.revision{main:2, sub:0}, mvcc.revision{main:4, sub:0}, mvcc.revision{main:6, sub:0}}
		g: created[{8 0}] ver[3], revs []mvcc.revision{mvcc.revision{main:8, sub:0}, mvcc.revision{main:10, sub:0}, mvcc.revision{main:12, sub:0}}
		g: created[{14 0}] ver[3], revs []mvcc.revision{mvcc.revision{main:14, sub:0}, mvcc.revision{main:14, sub:1}, mvcc.revision{main:16, sub:0}}
		g: created[{0 0}] ver[0], revs []mvcc.revision{}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK:

if len(g.revs) == nil {
    // preserve nils
    return nil
}
tmp := make([]revision, len(g.revs))
copy(tmp, g.revs)
return tmp

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the return type is *generation

I have the following

func cloneGeneration(g *generation) *generation {
	if g.revs == nil {
		return &generation{g.ver, g.created, nil}
	}
	tmp := make([]revision, len(g.revs))
	copy(tmp, g.revs)
	return &generation{g.ver, g.created, tmp}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok..

@fanminshi
Copy link
Member Author

via https://jenkins-etcd-public.prod.coreos.systems/job/etcd-ci-ppc64/1743/console

2017-08-01 03:15:30.669672 I | etcdserver/api/v3rpc: get error from resetTransport context canceled, transportMonitor returning
2017-08-01 03:15:30.669691 I | etcdserver/api/v3rpc: grpc: addrConn.transportMonitor exits due to: context canceled
Too many goroutines running after all test(s).
1 instances of:
google.golang.org/grpc.(*ClientConn).lbWatcher(...)
	/var/jenkins_home/workspace/etcd-ci-ppc64/gopath/src/google.golang.org/grpc/clientconn.go:499 +0x78
created by google.golang.org/grpc.DialContext.func3
	/var/jenkins_home/workspace/etcd-ci-ppc64/gopath/src/google.golang.org/grpc/clientconn.go:409 +0x194
1 instances of:
google.golang.org/grpc.(*addrConn).resetTransport(...)
	/var/jenkins_home/workspace/etcd-ci-ppc64/gopath/src/google.golang.org/grpc/clientconn.go:903 +0x754
google.golang.org/grpc.(*addrConn).transportMonitor(...)
	/var/jenkins_home/workspace/etcd-ci-ppc64/gopath/src/google.golang.org/grpc/clientconn.go:999 +0x460
google.golang.org/grpc.(*ClientConn).resetAddrConn.func1(...)
	/var/jenkins_home/workspace/etcd-ci-ppc64/gopath/src/google.golang.org/grpc/clientconn.go:640 +0x1bc
created by google.golang.org/grpc.(*ClientConn).resetAddrConn
	/var/jenkins_home/workspace/etcd-ci-ppc64/gopath/src/google.golang.org/grpc/clientconn.go:641 +0x5dc
exit status 1
FAIL	github.com/coreos/etcd/clientv3/integration	230.527s

Leaky test. I don't think it is related to this pr.

@heyitsanthony
Copy link
Contributor

that's a grpc leak, fine to ignore

@fanminshi
Copy link
Member Author

proxy-ci fails via #6934.
I don't believe this is cause by this pr.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

TestHashKVWhenCompacting: hashes differ
2 participants