Merge pull request #444 from tonistiigi/replace-locker
vendor: replace locker pkg for legaldocker-18.09
commit
2dcbb12f61
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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/>
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue