Merge pull request #444 from tonistiigi/replace-locker

vendor: replace locker pkg for legal
docker-18.09
Tõnis Tiigi 2018-06-08 11:31:07 -07:00 committed by GitHub
commit 2dcbb12f61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 185 additions and 162 deletions

View File

@ -10,8 +10,8 @@ import (
"path/filepath"
"sync"
"github.com/BurntSushi/locker"
"github.com/containerd/continuity/fs"
"github.com/docker/docker/pkg/locker"
iradix "github.com/hashicorp/go-immutable-radix"
"github.com/hashicorp/golang-lru/simplelru"
"github.com/moby/buildkit/cache"
@ -32,7 +32,7 @@ const keyContentHash = "buildkit.contenthash.v0"
func getDefaultManager() *cacheManager {
defaultManagerOnce.Do(func() {
lru, _ := simplelru.NewLRU(20, nil) // error is impossible on positive size
defaultManager = &cacheManager{lru: lru, locker: locker.NewLocker()}
defaultManager = &cacheManager{lru: lru, locker: locker.New()}
})
return defaultManager
}

View File

@ -5,9 +5,9 @@ import (
"net/http"
"sync"
"github.com/BurntSushi/locker"
"github.com/containerd/containerd/remotes"
"github.com/containerd/containerd/remotes/docker"
"github.com/docker/docker/pkg/locker"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/util/contentutil"
"github.com/moby/buildkit/util/imageutil"
@ -45,7 +45,7 @@ func New(with ...ImageMetaResolverOpt) llb.ImageMetaResolver {
platform: opts.platform,
buffer: contentutil.NewBuffer(),
cache: map[string]resolveResult{},
locker: locker.NewLocker(),
locker: locker.New(),
}
}

View File

@ -11,8 +11,8 @@ import (
"regexp"
"strings"
"github.com/BurntSushi/locker"
"github.com/boltdb/bolt"
"github.com/docker/docker/pkg/locker"
"github.com/moby/buildkit/cache"
"github.com/moby/buildkit/cache/metadata"
"github.com/moby/buildkit/identity"
@ -40,7 +40,7 @@ func NewSource(opt Opt) (source.Source, error) {
gs := &gitSource{
md: opt.MetadataStore,
cache: opt.CacheAccessor,
locker: locker.NewLocker(),
locker: locker.New(),
}
if err := exec.Command("git", "version").Run(); err != nil {

View File

@ -15,8 +15,8 @@ import (
"strings"
"time"
"github.com/BurntSushi/locker"
"github.com/boltdb/bolt"
"github.com/docker/docker/pkg/locker"
"github.com/moby/buildkit/cache"
"github.com/moby/buildkit/cache/metadata"
"github.com/moby/buildkit/snapshot"
@ -47,7 +47,7 @@ func NewSource(opt Opt) (source.Source, error) {
hs := &httpSource{
md: opt.MetadataStore,
cache: opt.CacheAccessor,
locker: locker.NewLocker(),
locker: locker.New(),
client: &http.Client{
Transport: transport,
},

View File

@ -36,7 +36,6 @@ github.com/docker/go-units v0.3.1
github.com/google/shlex 6f45313302b9c56850fc17f99e40caebce98c716
golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631
github.com/BurntSushi/locker a6e239ea1c69bff1cfdb20c4b73dadf52f784b6a
github.com/docker/docker 71cd53e4a197b303c6ba086bd584ffd67a884281
github.com/pkg/profile 5b67d428864e92711fcbd2f8629456121a56d91f

View File

@ -1,21 +0,0 @@
Package locker is a simple package to manage named ReadWrite mutexes. These
appear to be especially useful for synchronizing access to session based
information in web applications.
The common use case is to use the package level functions, which use a package
level set of locks (safe to use from multiple goroutines simultaneously).
However, you may also create a new separate set of locks.
All locks are implemented with read-write mutexes. To use them like a regular
mutex, simply ignore the RLock/RUnlock functions.
### Installation
go get github.com/BurntSushi/locker
### Documentation
http://godoc.org/github.com/BurntSushi/locker

View File

@ -1,24 +0,0 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>

View File

@ -1,108 +0,0 @@
/*
Package locker is a simple package to manage named ReadWrite mutexes. These
appear to be especially useful for synchronizing access to session based
information in web applications.
The common use case is to use the package level functions, which use a package
level set of locks (safe to use from multiple goroutines simultaneously).
However, you may also create a new separate set of locks.
All locks are implemented with read-write mutexes. To use them like a regular
mutex, simply ignore the RLock/RUnlock functions.
*/
package locker
// BUG(burntsushi): The locker here can grow without bound in long running
// programs. Since it's intended to be used in web applications, this is a
// major problem. Figure out a way to keep the locker lean.
import (
"fmt"
"sync"
)
// Locker represents the set of named ReadWrite mutexes. It is safe to access
// from multiple goroutines simultaneously.
type Locker struct {
locks map[string]*sync.RWMutex
locksRW *sync.RWMutex
}
var locker *Locker
func init() {
locker = NewLocker()
}
func Lock(key string) { locker.Lock(key) }
func Unlock(key string) { locker.Unlock(key) }
func RLock(key string) { locker.RLock(key) }
func RUnlock(key string) { locker.RUnlock(key) }
func NewLocker() *Locker {
return &Locker{
locks: make(map[string]*sync.RWMutex),
locksRW: new(sync.RWMutex),
}
}
func (lker *Locker) Lock(key string) {
lk, ok := lker.getLock(key)
if !ok {
lk = lker.newLock(key)
}
lk.Lock()
}
func (lker *Locker) Unlock(key string) {
lk, ok := lker.getLock(key)
if !ok {
panic(fmt.Errorf("BUG: Lock for key '%s' not initialized.", key))
}
lk.Unlock()
}
func (lker *Locker) RLock(key string) {
lk, ok := lker.getLock(key)
if !ok {
lk = lker.newLock(key)
}
lk.RLock()
}
func (lker *Locker) RUnlock(key string) {
lk, ok := lker.getLock(key)
if !ok {
panic(fmt.Errorf("BUG: Lock for key '%s' not initialized.", key))
}
lk.RUnlock()
}
func (lker *Locker) newLock(key string) *sync.RWMutex {
lker.locksRW.Lock()
defer lker.locksRW.Unlock()
if lk, ok := lker.locks[key]; ok {
return lk
}
lk := new(sync.RWMutex)
lker.locks[key] = lk
return lk
}
func (lker *Locker) getLock(key string) (*sync.RWMutex, bool) {
lker.locksRW.RLock()
defer lker.locksRW.RUnlock()
lock, ok := lker.locks[key]
return lock, ok
}
func (lker *Locker) deleteLock(key string) {
lker.locksRW.Lock()
defer lker.locksRW.Unlock()
if _, ok := lker.locks[key]; ok {
delete(lker.locks, key)
}
}

65
vendor/github.com/docker/docker/pkg/locker/README.md generated vendored Normal file
View File

@ -0,0 +1,65 @@
Locker
=====
locker provides a mechanism for creating finer-grained locking to help
free up more global locks to handle other tasks.
The implementation looks close to a sync.Mutex, however, the user must provide a
reference to use to refer to the underlying lock when locking and unlocking,
and unlock may generate an error.
If a lock with a given name does not exist when `Lock` is called, one is
created.
Lock references are automatically cleaned up on `Unlock` if nothing else is
waiting for the lock.
## Usage
```go
package important
import (
"sync"
"time"
"github.com/docker/docker/pkg/locker"
)
type important struct {
locks *locker.Locker
data map[string]interface{}
mu sync.Mutex
}
func (i *important) Get(name string) interface{} {
i.locks.Lock(name)
defer i.locks.Unlock(name)
return i.data[name]
}
func (i *important) Create(name string, data interface{}) {
i.locks.Lock(name)
defer i.locks.Unlock(name)
i.createImportant(data)
i.mu.Lock()
i.data[name] = data
i.mu.Unlock()
}
func (i *important) createImportant(data interface{}) {
time.Sleep(10 * time.Second)
}
```
For functions dealing with a given name, always lock at the beginning of the
function (or before doing anything with the underlying state), this ensures any
other function that is dealing with the same name will block.
When needing to modify the underlying data, use the global lock to ensure nothing
else is modifying it at the same time.
Since name lock is already in place, no reads will occur while the modification
is being performed.

112
vendor/github.com/docker/docker/pkg/locker/locker.go generated vendored Normal file
View File

@ -0,0 +1,112 @@
/*
Package locker provides a mechanism for creating finer-grained locking to help
free up more global locks to handle other tasks.
The implementation looks close to a sync.Mutex, however the user must provide a
reference to use to refer to the underlying lock when locking and unlocking,
and unlock may generate an error.
If a lock with a given name does not exist when `Lock` is called, one is
created.
Lock references are automatically cleaned up on `Unlock` if nothing else is
waiting for the lock.
*/
package locker // import "github.com/docker/docker/pkg/locker"
import (
"errors"
"sync"
"sync/atomic"
)
// ErrNoSuchLock is returned when the requested lock does not exist
var ErrNoSuchLock = errors.New("no such lock")
// Locker provides a locking mechanism based on the passed in reference name
type Locker struct {
mu sync.Mutex
locks map[string]*lockCtr
}
// lockCtr is used by Locker to represent a lock with a given name.
type lockCtr struct {
mu sync.Mutex
// waiters is the number of waiters waiting to acquire the lock
// this is int32 instead of uint32 so we can add `-1` in `dec()`
waiters int32
}
// inc increments the number of waiters waiting for the lock
func (l *lockCtr) inc() {
atomic.AddInt32(&l.waiters, 1)
}
// dec decrements the number of waiters waiting on the lock
func (l *lockCtr) dec() {
atomic.AddInt32(&l.waiters, -1)
}
// count gets the current number of waiters
func (l *lockCtr) count() int32 {
return atomic.LoadInt32(&l.waiters)
}
// Lock locks the mutex
func (l *lockCtr) Lock() {
l.mu.Lock()
}
// Unlock unlocks the mutex
func (l *lockCtr) Unlock() {
l.mu.Unlock()
}
// New creates a new Locker
func New() *Locker {
return &Locker{
locks: make(map[string]*lockCtr),
}
}
// Lock locks a mutex with the given name. If it doesn't exist, one is created
func (l *Locker) Lock(name string) {
l.mu.Lock()
if l.locks == nil {
l.locks = make(map[string]*lockCtr)
}
nameLock, exists := l.locks[name]
if !exists {
nameLock = &lockCtr{}
l.locks[name] = nameLock
}
// increment the nameLock waiters while inside the main mutex
// this makes sure that the lock isn't deleted if `Lock` and `Unlock` are called concurrently
nameLock.inc()
l.mu.Unlock()
// Lock the nameLock outside the main mutex so we don't block other operations
// once locked then we can decrement the number of waiters for this lock
nameLock.Lock()
nameLock.dec()
}
// Unlock unlocks the mutex with the given name
// If the given lock is not being waited on by any other callers, it is deleted
func (l *Locker) Unlock(name string) error {
l.mu.Lock()
nameLock, exists := l.locks[name]
if !exists {
l.mu.Unlock()
return ErrNoSuchLock
}
if nameLock.count() == 0 {
delete(l.locks, name)
}
nameLock.Unlock()
l.mu.Unlock()
return nil
}