From 63aa64d2406a2e6c9ea465ca108f1af2a699179e Mon Sep 17 00:00:00 2001 From: lorneli Date: Wed, 6 Sep 2017 20:56:34 +0800 Subject: [PATCH] lease: use monotime in time.Time for Go 1.9 The golang/time package tracks monotonic time in each time.Time returned by time.Now function for Go 1.9. Use time.Time to measure whether a lease is expired and remove previous pkg/monotime. Use zero time.Time to mean forever. No expiration when expiry.IsZero() is true. --- lease/lessor.go | 38 +++++++++++++++++++++-------------- pkg/monotime/issue15006.s | 6 ------ pkg/monotime/monotime.go | 26 ------------------------ pkg/monotime/nanotime.go | 24 ---------------------- pkg/monotime/nanotime_test.go | 22 -------------------- 5 files changed, 23 insertions(+), 93 deletions(-) delete mode 100644 pkg/monotime/issue15006.s delete mode 100644 pkg/monotime/monotime.go delete mode 100644 pkg/monotime/nanotime.go delete mode 100644 pkg/monotime/nanotime_test.go diff --git a/lease/lessor.go b/lease/lessor.go index 815e10c0f..5657a31c3 100644 --- a/lease/lessor.go +++ b/lease/lessor.go @@ -20,22 +20,18 @@ import ( "math" "sort" "sync" - "sync/atomic" "time" "github.com/coreos/etcd/lease/leasepb" "github.com/coreos/etcd/mvcc/backend" - "github.com/coreos/etcd/pkg/monotime" ) -const ( - // NoLease is a special LeaseID representing the absence of a lease. - NoLease = LeaseID(0) - - forever = monotime.Time(math.MaxInt64) -) +// NoLease is a special LeaseID representing the absence of a lease. +const NoLease = LeaseID(0) var ( + forever = time.Time{} + leaseBucketName = []byte("lease") // maximum number of leases to revoke per second; configurable for tests @@ -560,8 +556,10 @@ func (le *lessor) initAndRecover() { type Lease struct { ID LeaseID ttl int64 // time to live in seconds - // expiry is time when lease should expire; must be 64-bit aligned. - expiry monotime.Time + // expiryMu protects concurrent accesses to expiry + expiryMu sync.RWMutex + // expiry is time when lease should expire. no expiration when expiry.IsZero() is true + expiry time.Time // mu protects concurrent accesses to itemSet mu sync.RWMutex @@ -594,12 +592,18 @@ func (l *Lease) TTL() int64 { // refresh refreshes the expiry of the lease. func (l *Lease) refresh(extend time.Duration) { - t := monotime.Now().Add(extend + time.Duration(l.ttl)*time.Second) - atomic.StoreUint64((*uint64)(&l.expiry), uint64(t)) + newExpiry := time.Now().Add(extend + time.Duration(l.ttl)*time.Second) + l.expiryMu.Lock() + defer l.expiryMu.Unlock() + l.expiry = newExpiry } // forever sets the expiry of lease to be forever. -func (l *Lease) forever() { atomic.StoreUint64((*uint64)(&l.expiry), uint64(forever)) } +func (l *Lease) forever() { + l.expiryMu.Lock() + defer l.expiryMu.Unlock() + l.expiry = forever +} // Keys returns all the keys attached to the lease. func (l *Lease) Keys() []string { @@ -614,8 +618,12 @@ func (l *Lease) Keys() []string { // Remaining returns the remaining time of the lease. func (l *Lease) Remaining() time.Duration { - t := monotime.Time(atomic.LoadUint64((*uint64)(&l.expiry))) - return time.Duration(t - monotime.Now()) + l.expiryMu.RLock() + defer l.expiryMu.RUnlock() + if l.expiry.IsZero() { + return time.Duration(math.MaxInt64) + } + return l.expiry.Sub(time.Now()) } type LeaseItem struct { diff --git a/pkg/monotime/issue15006.s b/pkg/monotime/issue15006.s deleted file mode 100644 index c3132a1f0..000000000 --- a/pkg/monotime/issue15006.s +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (C) 2016 Arista Networks, Inc. -// Use of this source code is governed by the Apache License 2.0 -// that can be found in the COPYING file. - -// This file is intentionally empty. -// It's a workaround for https://github.com/golang/go/issues/15006 \ No newline at end of file diff --git a/pkg/monotime/monotime.go b/pkg/monotime/monotime.go deleted file mode 100644 index a5e16ce1d..000000000 --- a/pkg/monotime/monotime.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2016 The etcd Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package monotime - -import ( - "time" -) - -// Time represents a point in monotonic time -type Time uint64 - -func (t Time) Add(d time.Duration) Time { - return Time(uint64(t) + uint64(d.Nanoseconds())) -} diff --git a/pkg/monotime/nanotime.go b/pkg/monotime/nanotime.go deleted file mode 100644 index e3fc846ef..000000000 --- a/pkg/monotime/nanotime.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) 2016 Arista Networks, Inc. -// Use of this source code is governed by the Apache License 2.0 -// that can be found in the COPYING file. - -// Package monotime provides a fast monotonic clock source. -package monotime - -import ( - _ "unsafe" // required to use //go:linkname -) - -//go:noescape -//go:linkname nanotime runtime.nanotime -func nanotime() int64 - -// Now returns the current time in nanoseconds from a monotonic clock. -// The time returned is based on some arbitrary platform-specific point in the -// past. The time returned is guaranteed to increase monotonically at a -// constant rate, unlike time.Now() from the Go standard library, which may -// slow down, speed up, jump forward or backward, due to NTP activity or leap -// seconds. -func Now() Time { - return Time(nanotime()) -} diff --git a/pkg/monotime/nanotime_test.go b/pkg/monotime/nanotime_test.go deleted file mode 100644 index c22b328b1..000000000 --- a/pkg/monotime/nanotime_test.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (C) 2016 Arista Networks, Inc. -// Use of this source code is governed by the Apache License 2.0 - -// Package monotime provides a fast monotonic clock source. - -package monotime - -import ( - "testing" -) - -func TestNow(t *testing.T) { - for i := 0; i < 100; i++ { - t1 := Now() - t2 := Now() - // I honestly thought that we needed >= here, but in some environments - // two consecutive calls can return the same value! - if t1 > t2 { - t.Fatalf("t1=%d should have been less than or equal to t2=%d", t1, t2) - } - } -}