mirror of
https://github.com/containers/podman.git
synced 2025-05-20 08:36:23 +08:00

Renumber is a way of renumbering container locks after the number of locks available has changed. For now, renumber only works with containers. Signed-off-by: Matthew Heon <matthew.heon@pm.me>
101 lines
2.1 KiB
Go
101 lines
2.1 KiB
Go
package lock
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// Mutex holds a single mutex and whether it has been allocated.
|
|
type Mutex struct {
|
|
id uint32
|
|
lock sync.Mutex
|
|
allocated bool
|
|
}
|
|
|
|
// ID retrieves the ID of the mutex
|
|
func (m *Mutex) ID() uint32 {
|
|
return m.id
|
|
}
|
|
|
|
// Lock locks the mutex
|
|
func (m *Mutex) Lock() {
|
|
m.lock.Lock()
|
|
}
|
|
|
|
// Unlock unlocks the mutex
|
|
func (m *Mutex) Unlock() {
|
|
m.lock.Unlock()
|
|
}
|
|
|
|
// Free deallocates the mutex to allow its reuse
|
|
func (m *Mutex) Free() error {
|
|
m.allocated = false
|
|
|
|
return nil
|
|
}
|
|
|
|
// InMemoryManager is a lock manager that allocates and retrieves local-only
|
|
// locks - that is, they are not multiprocess. This lock manager is intended
|
|
// purely for unit and integration testing and should not be used in production
|
|
// deployments.
|
|
type InMemoryManager struct {
|
|
locks []*Mutex
|
|
numLocks uint32
|
|
localLock sync.Mutex
|
|
}
|
|
|
|
// NewInMemoryManager creates a new in-memory lock manager with the given number
|
|
// of locks.
|
|
func NewInMemoryManager(numLocks uint32) (Manager, error) {
|
|
if numLocks == 0 {
|
|
return nil, errors.Errorf("must provide a non-zero number of locks!")
|
|
}
|
|
|
|
manager := new(InMemoryManager)
|
|
manager.numLocks = numLocks
|
|
manager.locks = make([]*Mutex, numLocks)
|
|
|
|
var i uint32
|
|
for i = 0; i < numLocks; i++ {
|
|
lock := new(Mutex)
|
|
lock.id = i
|
|
manager.locks[i] = lock
|
|
}
|
|
|
|
return manager, nil
|
|
}
|
|
|
|
// AllocateLock allocates a lock from the manager.
|
|
func (m *InMemoryManager) AllocateLock() (Locker, error) {
|
|
m.localLock.Lock()
|
|
defer m.localLock.Unlock()
|
|
|
|
for _, lock := range m.locks {
|
|
if !lock.allocated {
|
|
lock.allocated = true
|
|
return lock, nil
|
|
}
|
|
}
|
|
|
|
return nil, errors.Errorf("all locks have been allocated")
|
|
}
|
|
|
|
// RetrieveLock retrieves a lock from the manager.
|
|
func (m *InMemoryManager) RetrieveLock(id uint32) (Locker, error) {
|
|
if id >= m.numLocks {
|
|
return nil, errors.Errorf("given lock ID %d is too large - this manager only supports lock indexes up to %d", id, m.numLocks-1)
|
|
}
|
|
|
|
return m.locks[id], nil
|
|
}
|
|
|
|
// FreeAllLocks frees all locks
|
|
func (m *InMemoryManager) FreeAllLocks() error {
|
|
for _, lock := range m.locks {
|
|
lock.allocated = false
|
|
}
|
|
|
|
return nil
|
|
}
|